Compare commits

...

1130 Commits

Author SHA1 Message Date
ErickSkrauch
677c10a61d Add tests 2019-08-23 00:15:10 +03:00
ErickSkrauch
3684a76ade Add getter for the OAuthServerException::redirectUri param and make it public 2019-08-23 00:00:15 +03:00
Andrew Millington
0b0b43d433 Merge pull request #1035 from matt-allan/prevent-public-client-confidential-grant
Prevent public clients from using the client_credentials grant type
2019-07-25 19:20:11 +01:00
Andrew Millington
cd8742f630 Reword changelog 2019-07-25 19:14:08 +01:00
Andrew Millington
2097edd6eb Update changelog 2019-07-25 19:12:33 +01:00
Andrew Millington
705120c974 Add blank space to keep formatting consistent 2019-07-25 19:09:47 +01:00
Andrew Millington
8a78e00a2e Add blank line above throw 2019-07-25 19:04:44 +01:00
Matt Allan
3413c20590 Prevent public clients from using the client_credentials grant type
See https://tools.ietf.org/html/rfc6749#section-4.4.2
2019-07-22 18:21:29 -04:00
Andrew Millington
e1dc4d708c Update changelog for release of version 8 2019-07-13 19:58:26 +01:00
Andrew Millington
18dabd36e3 Remove branch 8.0.0 from travis checks 2019-07-13 19:56:44 +01:00
Andrew Millington
1a3107b4fc Merge pull request #1033 from thephpleague/8.0.0
8.0.0
2019-07-13 19:46:10 +01:00
Andrew Millington
1d9ca35fec Merge pull request #1032 from thephpleague/update-examples-for-version-8
Update Examples for Version 8
2019-07-13 19:39:38 +01:00
Andrew Millington
c7f998ee02 Add PR number for JTI PR to changelog 2019-07-13 18:03:24 +01:00
Andrew Millington
4b1c9ed503 Merge pull request #1031 from Sephster/remove-jti-from-header
Remove JTI Claim From JWT Header
2019-07-13 17:50:20 +01:00
Andrew Millington
dc3c74601a Update changelog 2019-07-13 17:52:35 +01:00
Andrew Millington
f5e910e6ec Remove jti replication from JWT Header 2019-07-13 17:51:56 +01:00
Andrew Millington
2b7923c593 Fix inheritdoc case 2019-07-13 17:49:26 +01:00
Andrew Millington
3f95c0d11e Update validateClient arguments list 2019-07-13 17:40:38 +01:00
Andrew Millington
4be97e6fd0 Update composer dependencies and remove mustValidateSecret 2019-07-13 17:37:45 +01:00
Andrew Millington
aba5353257 Add validateClient() function to ClientRepository 2019-07-13 17:31:09 +01:00
sephster
7f0879b8b4 Change header type 2019-07-02 22:52:13 +01:00
sephster
cb9aa25c89 Re-add removed changelog instances 2019-07-02 22:51:12 +01:00
sephster
a6a499f8fb Remove Simon Hamp from README 2019-07-02 22:20:37 +01:00
Andrew Millington
ccf36588ee Merge pull request #1024 from Sephster/update-dependencies
Update Dependencies
2019-07-02 22:15:29 +01:00
sephster
6b2a3db185 Removing php stan strict rules 2019-07-02 22:10:17 +01:00
sephster
1a6ebdf81c Fix order of imports 2019-07-02 19:24:19 +01:00
sephster
46c86ed5b1 Apply style fix 2019-07-02 19:21:13 +01:00
sephster
a92a274d15 Use reflection instead of extension in test 2019-07-02 19:09:47 +01:00
sephster
c4c354e2df Fix phpstan issues 2019-07-01 19:17:43 +01:00
sephster
7bc1ec643e Remove unused import 2019-06-27 13:24:58 +01:00
sephster
51b97f87c1 Fix issues setting attributes on requests 2019-06-27 13:15:37 +01:00
sephster
e3b23fa826 Update dependencies and fix PHPUnit tests 2019-06-27 12:54:22 +01:00
Andrew Millington
bac79a26a8 Merge pull request #1010 from iansltx/protect-client-entity-gets
Ensure unvalidated ClientEntity gets throw/emit if they return null
2019-06-23 13:54:14 -04:00
sephster
012808f094 Update changelog 2019-06-23 17:56:32 +01:00
sephster
0db54cf1e5 Reinstate use for ClientEntityInterface 2019-06-23 17:40:39 +01:00
sephster
c7d047f7f5 Remove extra line spaces 2019-06-23 17:35:24 +01:00
sephster
e1324b88b2 Merge remote-tracking branch 'upstream/8.0.0' into protect-client-entity-gets 2019-06-23 17:23:40 +01:00
Andrew Millington
c60e8e3581 Merge pull request #1011 from iansltx/readme-release-notes-73-cleanup
Update release notes, clean up readme, add PHP 7.3 test for v8
2019-06-18 17:41:52 -04:00
sephster
e0ee244506 Remove duplicate entries from changelog 2019-06-18 22:30:17 +01:00
Ian Littman
8b5841870f Add more detail/precision to 8.0.0 changelog around breaking changes 2019-05-19 21:01:46 -05:00
Ian Littman
048e45d8cd Add more recent 7.x releases to changelog 2019-05-19 21:01:46 -05:00
Ian Littman
bf75596989 Update security contact email to current maintainer 2019-05-19 21:01:41 -05:00
Ian Littman
c5cfc0a371 Remove dead Commercial Support link 2019-05-19 20:52:28 -05:00
Andrew Millington
5ab4323856 Merge pull request #1014 from Sephster/drop-php-70-support
Drop php 7.0 support
2019-05-14 21:42:12 +01:00
sephster
28709f300f Add pull request number to changelog 2019-05-14 21:30:30 +01:00
sephster
bd483d701b Remove support for PHP 7.0 2019-05-14 21:26:17 +01:00
Andrew Millington
3dc324af6e Merge pull request #1013 from Sephster/8.0.0
Add The Latest Changes from Master into 8.0.0 Branch
2019-05-14 21:09:46 +01:00
sephster
17923634bf Set private keys in tests 2019-05-14 20:56:54 +01:00
sephster
a1cf22a3a9 Remove duplicate setting of expirydatetime 2019-05-14 16:11:34 +01:00
sephster
86d1581cd9 Remove unused imports 2019-05-14 15:57:13 +01:00
sephster
521ed9a8cb Merge master into 8.0.0 branch 2019-05-14 15:46:01 +01:00
Andrew Millington
1bbcb57d63 Merge pull request #1009 from iansltx/skip-s256-if-not-installed
Skip SHA256 verifier if system doesn't support sha256
2019-05-14 14:55:39 +01:00
Andrew Millington
93d4b947d8 Merge pull request #1008 from iansltx/typehints-and-exts
Typehint ServerRequestInterface on OAuthServerException, explicitly require ext-json
2019-05-13 10:25:32 +01:00
Ian Littman
27d5c5ed8d Ensure unvalidated ClientEntity gets throw/emit if they return null
In many cases, we validate client info before pulling from client itself
from the repository, in which case it's safe to assume that you can grab
the client once validation passes. However on implicit/auth code grants
we don't have this guarantee due to non-confidential clients that just
reference the client ID. In those cases the client may supply a client
ID that doesn't exist, and we don't do a validation step before pulling
it from the repo.

The issue with that is that ClientRepository doesn't actually enforce
returning a ClientInterface via typehint, nor does it even suggest an
exception to throw if the client doesn't exist. So in most places we
do an instanceof check after the repository returns and throw/emit an
error event if the client doesn't exist.

This approach ends up being a bit error-prone; we missed one case where
we should've been doing this check: in the access token request on an
auth code grant. We don't do enough validation beforehand to assume that
the incoming request has an accurate client ID, so L96 could absolutely
be a method call on a non-object.

This commit centralizes the return-check-emit-throw logic so it's a
one-liner for wherever we need it, including the access token request
processor for auth code grants.
2019-05-11 14:35:59 -05:00
Ian Littman
4ecd3131c1 Skip SHA256 verifier if system doesn't support sha256 2019-05-11 14:23:56 -05:00
Ian Littman
3fdfbe11f6 Explicitly require ext-json
Makes phpstorm happier; take or leave
2019-05-11 13:37:22 -05:00
Ian Littman
42df2d9c47 Add typehints to OAuthServerException calls 2019-05-11 13:35:24 -05:00
Andrew Millington
2eb1cf79e5 Update changelog for version 7.4.0 2019-05-05 10:22:01 +01:00
Andrew Millington
382b6f5fbf Merge pull request #1000 from filecage/master
Optional Refresh Tokens
2019-05-05 09:48:53 +01:00
sephster
86869eafbb Add whitespace around control blocks 2019-05-05 09:03:13 +01:00
sephster
9236e842d9 Clarify changelog message 2019-05-05 08:58:34 +01:00
filecage
9bc7f6c8c5 removing simplified_null_return 2019-04-29 19:13:26 +02:00
David
1e9a468e66 Merge branch 'master' into master 2019-04-12 11:17:37 +02:00
Andrew Millington
c7f4998497 Update links 2019-03-29 18:19:35 +00:00
Andrew Millington
0a78236f17 Update changelog for version 7.3.3 2019-03-29 18:18:35 +00:00
Andrew Millington
a68f8001a4 Merge pull request #1006 from marc-mabe/fix-958-error_description
spec compliant 'error_description' but keep 'message' for BC
2019-03-29 16:28:33 +00:00
Marc Bennewitz
b88198a9a4 spec compliant 'error_description' but keep 'message' for BC 2019-03-29 16:00:26 +01:00
filecage
8cf39fd9cd applies style CI diff 2019-03-16 13:15:38 +01:00
filecage
6f6820f629 removes @var hints
the @var hints make PHP stan fail together with PHPUnit 6.3
2019-03-16 13:12:34 +01:00
filecage
0742d5150c explicit is better than implicit :) 2019-03-13 10:08:57 +01:00
filecage
64f0d89fad getNewRefreshToken() can also return NULL 2019-03-11 23:28:47 +01:00
filecage
ebf78132d7 refreshTokenRepository parameter can not be null, condition is obsolete 2019-03-11 23:28:20 +01:00
filecage
aa5bbe5f06 boyscout: style CI tweaks 2019-03-11 23:26:35 +01:00
filecage
66d4ce6de8 Update CHANGELOG.md 2019-03-08 18:21:55 +01:00
filecage
2ea76ca4fd Adds handling for null issued refresh token to Grant implementations 2019-03-08 18:19:16 +01:00
filecage
b2840474fd AbstractGrant no longer tries to issue a refresh token if the Repository returned null 2019-03-08 18:16:16 +01:00
Andrew Millington
0227f14b7b Merge pull request #988 from lordrhodos/feature/test-cleanup
Cleanup: remove unused local variable $scopeEntity from ImplicitGrantTest
2019-01-22 20:59:33 +00:00
Patrick Rodacker
fad42a88fd removes unused local variable $scopeEntity from ImplicitGrantTest 2019-01-20 22:11:22 +01:00
Andrew Millington
d7defafd83 Merge pull request #963 from marc-mabe/date-time-handling
BC-Break: cleanup DateTime handline for 8.0.0
2018-12-19 13:10:20 +00:00
sephster
16f37560d4 Merge latest version of 8 branch 2018-12-19 13:03:10 +00:00
sephster
5ed8e59ef3 Update changelog 2018-12-19 12:58:11 +00:00
sephster
c2cd12e0b8 Remove return types 2018-12-19 12:54:26 +00:00
Andrew Millington
8e9368cf44 Merge pull request #978 from Devristo/fix-http-basic-respond-to-access-token-request
Fixed respondToAccessTokenRequest using Http Basic Auth
2018-12-10 23:07:58 +00:00
sephster
894724c45b Remove invalid commenting 2018-12-10 23:01:45 +00:00
sephster
fd65bf9e54 Streamline tests 2018-12-10 22:51:58 +00:00
Andrew Millington
2a16dbeb7f Merge pull request #981 from Sephster/support-php-7.3
Add support for PHP 7.3
2018-12-06 23:53:55 +00:00
sephster
faa350792a Add support for PHP 7.3 2018-12-06 23:46:28 +00:00
Chris Tanaskoski
b6955a6c65 Fixed respondToAccessTokenRequest such that it accepts client_id through request body and Http Basic Auth 2018-11-30 10:19:06 +01:00
Chris Tanaskoski
ec8a663a81 Added test for respondToAccessTokenRequest using Http Basic Auth for client credentials 2018-11-29 09:28:36 +01:00
Andrew Millington
dc3181bbb0 Merge pull request #977 from spideyfusion/symfony-community-integration
Add Symfony community integration to README.md
2018-11-28 12:47:30 +00:00
Petar Obradović
1e3a7adb19 Add Symfony community integration to README.md 2018-11-28 12:24:16 +01:00
sephster
b71f382cd7 Update changelog 2018-11-21 21:42:43 +00:00
Andrew Millington
9783388523 Merge pull request #969 from ceeram/fix-bc-break
Fix bc breaking change
2018-11-21 21:38:37 +00:00
sephster
46493c461e Update changelog for 7.3.2 release 2018-11-21 21:29:55 +00:00
sephster
8b421818f2 Add blank line to better format 2018-11-21 21:26:54 +00:00
Marc Ypes
b09154af33 Add test to prove bc break 2018-11-16 13:29:47 +01:00
Marc Ypes
f1454cde36 Fix bc breaking change 2018-11-16 12:44:41 +01:00
Andrew Millington
f2cd3646ff Merge pull request #970 from Sephster/interface-revert
Revert Interface Change
2018-11-15 22:37:18 +00:00
sephster
7839a61170 Update changelog 2018-11-15 22:33:34 +00:00
sephster
443d7c485a Revert interface change so class can be extende 2018-11-15 22:22:08 +00:00
Andrew Millington
a61c6a318a Update changelog for 7.3.0 release 2018-11-13 20:17:20 +00:00
Andrew Millington
eea9c30e70 Merge pull request #967 from Sephster/password-grant-use-invalid-grant
Password Grant Should Issue an invalid_grant Error When Credentials are Incorrect
2018-11-13 18:28:09 +00:00
sephster
a936962716 Update changelog 2018-11-13 18:27:03 +00:00
sephster
685dc6edea Update test 2018-11-13 18:19:20 +00:00
sephster
2b4974b697 Change to use invalid_grant 2018-11-13 18:18:07 +00:00
sephster
94e75ba6f3 Fix bug 2018-11-13 12:56:06 +00:00
Andrew Millington
efa8ef6fce Merge pull request #965 from ceeram/add-previous
Include previous exception in catch and throw
2018-11-13 12:44:43 +00:00
sephster
7982275757 Fix docblock alignment 2018-11-13 12:34:16 +00:00
sephster
f6c1070ccc Add use Throwable 2018-11-13 12:32:52 +00:00
sephster
d64fb3f526 Merge master into this branch 2018-11-13 12:28:39 +00:00
Andrew Millington
95a9f4649d Merge pull request #966 from ceeram/fully_qualified_strict_types
Replace fqn with unqualified name
2018-11-13 11:58:31 +00:00
Marc Ypes
4bb5b747c1 Replace fqn with unqualified name 2018-11-13 01:33:11 +01:00
Marc Ypes
5868996961 Add test for previous exceptions 2018-11-13 00:25:22 +01:00
sephster
9542af627e Update changelog 2018-11-12 19:57:35 +00:00
Marc Ypes
3b983ad0b4 Include previous exception in catch and throw 2018-11-12 13:58:31 +01:00
sephster
34ec35019b Remove additional whitespace 2018-11-08 13:10:22 +00:00
Marc Bennewitz
16f9de86f2 cleanup DateTime handline
* DateTime -> DateTimeImmutable
* DateTime::format('U') -> DateTime::getTimestamp()
* (new DateTime())->getTimestamp() -> time()
2018-11-08 12:45:18 +01:00
Andrew Millington
ac818bd921 Minor formatting adjustment 2018-11-06 21:42:05 +00:00
Andrew Millington
73698e28d9 Update CHANGELOG.md 2018-11-06 21:38:31 +00:00
Andrew Millington
c87be9477c Merge pull request #960 from marc-mabe/stateless-server
Make AuthorizationServer stateless
2018-11-06 21:34:26 +00:00
Marc Bennewitz
d288a2ad8a Make AuthorizationServer stateless 2018-11-05 09:08:02 +01:00
Andrew Millington
a34f5dd7db Merge pull request #953 from Sephster/code-tidyup
Code Tidyup
2018-10-13 17:06:21 +01:00
sephster
c0efdf0dd0 Revert changes to throws and returns ordering 2018-10-13 16:54:31 +01:00
sephster
f96fca3b48 Minor code tidyup 2018-10-13 16:44:40 +01:00
sephster
20b355b025 Re-order docblock throws 2018-10-13 16:31:36 +01:00
sephster
793f65d3a3 Remove unused scope entity interface 2018-10-13 16:14:15 +01:00
sephster
322b55eddf Remove getScopes function and use validateScopes instead 2018-10-13 16:11:44 +01:00
sephster
50ab9dd8ac Remove unused import 2018-10-13 15:28:39 +01:00
sephster
b624124d5a Chaneg param types to satisfy PHPStan 2018-10-13 15:25:49 +01:00
sephster
dbf2b55bc5 Fix docblock alignment 2018-10-13 15:16:50 +01:00
sephster
b11d628e8b Change docblock type for 2018-10-13 14:49:29 +01:00
sephster
0515129c9c Fix coding standards issues 2018-10-13 14:37:36 +01:00
sephster
50566cdc87 Reduce complexity of respondToAccessTokenRequest 2018-10-13 14:34:35 +01:00
sephster
b4d88995de Add throws tag for DateInterval exception 2018-10-13 13:42:27 +01:00
sephster
398029be56 Add roave security advisories 2018-10-13 13:35:36 +01:00
sephster
30ed221481 Add Andy to authors list 2018-10-13 13:27:31 +01:00
sephster
939c0619d0 Shorten variable name 2018-10-13 13:22:27 +01:00
sephster
4042a31159 Update composer dependency versions 2018-10-13 13:17:45 +01:00
Andrew Millington
0bdd02cdb4 Merge pull request #952 from Sephster/add-scope-entity-trait
Add Scope Entity Trait
2018-10-13 13:14:33 +01:00
sephster
7bf7700645 Update changelog 2018-10-12 23:32:44 +01:00
sephster
d76025d613 Change example to use scope trait 2018-10-12 23:23:24 +01:00
sephster
d6792c1662 Add scope entity trait 2018-10-12 23:05:07 +01:00
Andrew Millington
9882f6716c Merge pull request #923 from christiaangoossens/fix_implicit_grant_scopes
ImplicitGrant finalizes scopes without user identifier
2018-09-23 18:31:53 +01:00
sephster
71c605117a Add missing word 2018-09-23 18:31:26 +01:00
sephster
6bc6ac09d2 Update changelog 2018-09-23 18:30:14 +01:00
Andrew Millington
fe421878e6 Merge pull request #938 from Sephster/force-pkce-for-public-clients
Force PKCE for public clients
2018-09-21 20:50:46 +01:00
sephster
0c2356a508 Fix file names for code challenge verifier tests 2018-09-21 20:43:04 +01:00
sephster
9645119ccb Fix missing comma 2018-09-21 20:35:04 +01:00
sephster
da2742bea7 Add details on client validation changes 2018-09-21 20:32:47 +01:00
sephster
efb5ce5e2a Update changelog 2018-09-21 20:29:27 +01:00
sephster
1ddc27e792 Add code challenge verifier tests 2018-09-21 20:12:05 +01:00
Andrew Millington
b7b7dda28c Merge pull request #945 from ezimuel/add-expressive-readme
Added Expressive in the community integration of README
2018-09-19 11:28:31 +01:00
Enrico Zimuel
ef864b5cba Added Expressive in the community integration of README 2018-09-19 12:02:06 +02:00
sephster
fcd6eb8a3c Fix variable name 2018-09-18 18:01:24 +01:00
sephster
133d9cc97a Fix missing 2018-09-18 17:51:11 +01:00
Andrew Millington
592dd2f433 Fix typo in function name 2018-09-17 20:10:26 +01:00
sephster
4a464dd336 Fix coding standard issue 2018-09-17 12:49:37 +01:00
sephster
970df8f34b Add code challenge verifiers 2018-09-17 12:48:32 +01:00
sephster
6a1645aebc Start to add code challenge verifier interfaces 2018-09-14 18:56:22 +01:00
sephster
e3e7abf41e Set default isConfidential to false for client entity 2018-09-03 13:09:52 +01:00
sephster
d831868d58 Fix getClientEntity parameters 2018-09-02 16:27:31 +01:00
sephster
36bf4ff8f2 Fix accidental paste of code 2018-09-02 16:19:47 +01:00
sephster
07ebe43b91 Change else if to elseif 2018-09-02 16:17:34 +01:00
sephster
5d3d9d95be Remove extra line 2018-09-02 15:46:59 +01:00
sephster
e85a8e31e8 Remove assignment as not needed 2018-09-02 14:58:02 +01:00
sephster
de899fbe0a Fix incorrect usage of isConfidential 2018-09-01 15:05:12 +01:00
sephster
3eabbafe5b Client says if it is confidential instead of repository 2018-09-01 14:53:27 +01:00
sephster
cfa9b8d3b4 Move grant check for client back to validate method 2018-09-01 14:38:31 +01:00
sephster
060a090479 Change tests to use validClient instead of getClientEntity 2018-09-01 14:26:22 +01:00
sephster
46c2f99b06 Change function name to be more explicit 2018-09-01 13:17:36 +01:00
Andrew Millington
27b956c149 Merge pull request #932 from JasonTheAdams/patch-1
Added docbloc to UniqueTokenIdentifierConstraintViolationException
2018-08-19 11:39:03 +01:00
Jason Adams
6949a007e5 Added docbloc to UniqueTokenIdentifierConstraintViolationException 2018-08-18 16:57:31 -07:00
sephster
74495cac49 Set proper confidential settings in existing tests 2018-08-16 12:59:10 +01:00
Andrew Millington
fb43801458 Change function name to setConfidential() 2018-08-15 21:40:41 +01:00
sephster
8ab27ede39 Add test to ensure public clients are asked to provide a code challenge 2018-08-13 22:54:12 +01:00
sephster
0105a20126 Reverted tests to remove isConfidential check 2018-08-13 22:00:34 +01:00
sephster
491852b521 Move code challenge check to auth code request 2018-08-13 21:47:53 +01:00
sephster
7f2fd7b22c Add set confidential to clients for tests 2018-08-13 21:21:59 +01:00
Andrew Millington
abef682031 Add setIsConfidential to client stub for tests 2018-08-12 20:34:58 +01:00
Andrew Millington
04807a1e2a Fix incorrect variable reference 2018-08-12 20:29:39 +01:00
Andrew Millington
d07b5a4a03 Add isConfidential function to client entity trait 2018-08-12 20:26:46 +01:00
Andrew Millington
838f206832 Tidy up comments 2018-08-12 20:09:55 +01:00
Andrew Millington
972808561d Add optional code challenge check for public clients 2018-08-12 20:06:34 +01:00
Andrew Millington
5ad00b0e33 Remove enableCodeExchangeProof function 2018-07-29 22:34:37 +01:00
Andrew Millington
f49cc65c13 Change to store code challenge and method whenever sent for PKCE 2018-07-29 19:56:30 +01:00
Christiaan Goossens
acf16e924a Actually use finalizedScopes in access token 2018-07-13 13:11:18 +02:00
Christiaan Goossens
a479b5762e Fix implicit grant scopes 2018-07-13 11:47:32 +02:00
Andrew Millington
dc2a048b95 Merge pull request #919 from Sephster/fix-909-v2
Fix 909
2018-06-24 13:55:33 +01:00
Andrew Millington
0c542637fe Merge branch '8.0.0' into fix-909-v2 2018-06-24 13:51:04 +01:00
Andrew Millington
0cdd535f7d Add changes to changelog 2018-06-24 13:48:52 +01:00
Andrew Millington
2fcee76d13 Remove unused stub function 2018-06-24 13:39:40 +01:00
Andrew Millington
574299d862 Fix tests 2018-06-24 13:38:55 +01:00
Andrew Millington
dad3b1e1c9 Remove unused test 2018-06-24 13:32:49 +01:00
Andrew Millington
7df0dfff9d Remove double function calls 2018-06-24 13:31:38 +01:00
Andrew Millington
ca5fe10934 Fix merge issues 2018-06-24 01:30:15 +01:00
Andrew Millington
369c7005a3 Merge master into version 8 branch 2018-06-24 01:10:02 +01:00
Andrew Millington
8184f771d4 Update for version 7.2.0 2018-06-23 17:57:59 +01:00
Andrew Millington
51b3b415b4 Update changelog for version 4.1.7 2018-06-23 17:46:19 +01:00
Andrew Millington
e3ad09d4a2 Update unreleased link in changelog 2018-06-23 17:35:51 +01:00
Andrew Millington
aeb1fe48d3 Add missing 4.1.6 release to changelog 2018-06-23 17:35:14 +01:00
Andrew Millington
f54980da25 Update changelog to add PR 917 2018-06-21 23:24:13 +01:00
Andrew Millington
105834af96 Merge pull request #917 from Erikvv/master
Allow 640 as key file permisions
2018-06-21 23:16:13 +01:00
Erik van Velzen
ffffc4bfeb Allow 640 as key file permisions 2018-06-21 17:02:01 +02:00
Andrew Millington
a77732e97c Merge pull request #912 from fizzka/extract-validate-uri
Extract validate uri
2018-06-15 14:42:01 +01:00
Ilya Bulah
614bba2c11 update changelog 2018-06-15 15:57:01 +03:00
Ilya Bulah
224763cda6 Fix docblock 2018-06-15 00:06:33 +03:00
Ilya Bulah
a31bc7d4cc Extract validateRedirectUri() 2018-06-14 23:50:58 +03:00
Ilya Bulah
0d20c755d4 Formatting 2018-06-14 23:50:58 +03:00
Ilya Bulah
e36ff17ad9 Fix psr2 2018-06-14 23:15:01 +03:00
Andrew Millington
a339d99135 Change sentence 2018-06-08 11:19:27 +01:00
Andrew Millington
a7a1065e38 Merge pull request #908 from fizzka/update-encryptionKey-comments
update encryptionKey comments
2018-06-05 10:34:56 +01:00
Andrew Millington
09bf988922 Add capital letter to start of class doc summary 2018-06-05 10:34:12 +01:00
Ilya Bulakh
a571e2262b Update CryptTrait.php 2018-06-04 16:32:02 +03:00
Andrew Millington
519543e925 Merge pull request #703 from iansltx/exception-has-redirect
Add hasRedirect() method for OAuthServerException

Fixes #694
2018-05-25 10:09:15 +01:00
Andrew Millington
3614f8bd7c Update changelog 2018-05-25 10:03:58 +01:00
Andrew Millington
e4a7fea834 Move OAuthServerExceptionTest to appropriate folder 2018-05-25 10:00:21 +01:00
Andrew Millington
68c9fbd83c Add a summary for hasRedirect function 2018-05-25 09:53:59 +01:00
Andrew Millington
466e1a639d Merge remote-tracking branch 'upstream/master' into exception-has-redirect 2018-05-25 09:49:14 +01:00
Andrew Millington
d7ab153500 Merge pull request #905 from Sephster/add-test-for-unsigned-token-exception
Add Exception Detection Test for Unsigned JWT
2018-05-25 09:42:19 +01:00
Andrew Millington
72ead2e3ce Fix unused use statement 2018-05-24 12:23:26 +01:00
Andrew Millington
ae4ab26aaf Add test for unsigned access token 2018-05-24 12:19:55 +01:00
Andrew Millington
ca6be0577c Merge pull request #874 from lookyman/access-token-jwt
Generalized access token format
2018-05-24 11:00:29 +01:00
Andrew Millington
ef75d13255 Update changelog 2018-05-23 16:44:00 +01:00
Andrew Millington
bd741e9203 Update travis to check 8.0.0 branch 2018-05-23 16:39:55 +01:00
Andrew Millington
aac64e49cf Fix style issue 2018-05-23 16:36:43 +01:00
Andrew Millington
61156ef8c7 Use __toString() for access token 2018-05-23 16:34:39 +01:00
Andrew Millington
2a7f671a95 Merge pull request #904 from dzibma/master
Fix uncaught exception produced by unsigned token
2018-05-22 18:13:17 +01:00
Andrew Millington
02609c37cc Update changelog 2018-05-22 18:10:19 +01:00
Martin Dzibela
9941a96feb Fix uncaught exception produced by unsigned token 2018-05-22 14:22:12 +02:00
Andrew Millington
4b0383b16c Updated changelog 2018-05-21 16:20:48 +01:00
Andrew Millington
4aeb92aa98 Merge remote-tracking branch 'upstream/8.0.0' into access-token-jwt 2018-05-21 16:18:24 +01:00
Andrew Millington
b182389395 Remove native type hints 2018-05-21 15:45:09 +01:00
Andrew Millington
92f598d1dc Merge pull request #899 from Sephster/fix-745
Only Add Authenticate Header if Present in Original Request - Tests
2018-05-21 15:44:13 +01:00
Andrew Millington
a40092ff54 Update changelog to fix merge conflict 2018-05-21 15:28:42 +01:00
Andrew Millington
2e47fa7fca Add PR reference 2018-05-21 15:01:37 +01:00
Andrew Millington
fc55621f20 Add link to 7.1.1 release in changelog 2018-05-21 15:00:06 +01:00
Andrew Millington
beec37d95f Modify changelog for 7.1.1 release 2018-05-21 14:58:56 +01:00
Andrew Millington
98812e6fab Update changelog 2018-05-21 11:21:44 +01:00
Andrew Millington
354aed7671 Merge in master 2018-05-21 10:53:24 +01:00
Andrew Millington
5a499bf03c Merge pull request #902 from Sephster/fix-745-without-tests
Only Add Authenticate Header if Present in Original Request. Fix #745
2018-05-17 13:34:30 +01:00
Andrew Millington
2e3ee60a2a Remove additional whitespace 2018-05-17 13:27:30 +01:00
Andrew Millington
0242d0c996 Remove spaces at end of line 2018-05-17 13:21:39 +01:00
Andrew Millington
3ea0cdc936 Set authScheme 2018-05-17 13:19:32 +01:00
Andrew Millington
19d782d223 Fix alignment 2018-05-17 13:13:30 +01:00
Andrew Millington
8a25e0a01b Update changelog 2018-05-17 13:12:32 +01:00
Andrew Millington
a3d4f583ed Fix #745 2018-05-17 13:06:03 +01:00
Andrew Millington
28276cb688 Add PSR-7 to the requirements in the readme
This fixes issue #640
2018-05-16 13:36:29 +01:00
Andrew Millington
b1b33207ab Fix namespacing for Exception test 2018-05-13 18:02:23 +01:00
Andrew Millington
793000f149 Fix ServerRequestInterface docblock type 2018-05-13 17:52:45 +01:00
Andrew Millington
f8c2e721a0 Remove return voids and fix docblock and use orders 2018-05-13 17:41:21 +01:00
Andrew Millington
cbce5f45ba Fix case for serverRequest variable and remove unused variable 2018-05-13 17:38:07 +01:00
Andrew Millington
c2dcdee266 Change order of use statements 2018-05-13 17:34:06 +01:00
Andrew Millington
33ce849617 Add tests for invalid client exception 2018-05-13 17:29:07 +01:00
Andrew Millington
ff5e9f57a5 Only add authenticate header if present in original request thephpleague/oauth2-server#745 2018-05-10 22:07:03 +01:00
Lukáš Unger
577065c270 Use native typehints 2018-05-08 11:35:06 +02:00
Lukáš Unger
a1da9beb92 Removed convertToJWT() method from AccessTokenEntityInterface 2018-05-07 20:37:20 +02:00
Andrew Millington
48ce5f36cf Change function name to be less technically specific 2018-05-07 20:37:20 +02:00
Lukáš Unger
fd72d79ad3 Generalized access token format 2018-05-07 20:37:20 +02:00
Andrew Millington
35c6f28aef Add drupal integration to the readme 2018-05-03 17:06:27 +01:00
Andrew Millington
bd47b58f81 Update changelog for version 7.1.0 2018-04-22 15:16:23 +01:00
Andrew Millington
e38ea4ab34 Update code of conduct link in the readme 2018-04-22 12:58:05 +01:00
Andrew Millington
8b40858509 Rename CONDUCT.md to CODE_OF_CONDUCT.md 2018-04-21 22:25:51 +01:00
Andrew Millington
aa5cc5eac7 Adding contact email address 2018-04-21 22:22:53 +01:00
Andrew Millington
38f26d5229 Update our code of conduct 2018-04-21 22:07:30 +01:00
Andrew Millington
a5a51fad95 Add PR 893 to the changelog 2018-04-21 22:05:08 +01:00
Andrew Millington
52d7952ba5 Merge pull request #893 from Sephster/fix-exception-hint
Change hint so it applies to both the auth and access token requests
2018-04-21 22:02:09 +01:00
Andrew Millington
2375b8c7f3 Merge pull request #856 from lookyman/phpstan-level-7
PHPStan level 7
2018-04-21 22:01:25 +01:00
Andrew Millington
f9a91a79c2 Put upgrade of PHPStan under changed category 2018-04-21 21:59:47 +01:00
Andrew Millington
242dd4dcfe Fix docblock 2018-04-21 21:51:25 +01:00
Andrew Millington
c94ec122aa Fix PR number for changelog 2018-04-21 21:41:48 +01:00
Andrew Millington
05f5d90034 Update changelog 2018-04-21 21:39:28 +01:00
Andrew Millington
491c23c1e9 Merge remote-tracking branch 'upstream/master' into phpstan-level-7 2018-04-21 21:37:24 +01:00
Andrew Millington
27323b5c9a Fix spacing issue 2018-04-21 21:31:48 +01:00
Andrew Millington
80bc291c51 Added null checks before calling set functions 2018-04-21 21:29:21 +01:00
Andrew Millington
8a619e5c1e Change hint so it applies to both the auth and access token requests 2018-04-21 18:07:38 +01:00
Andrew Millington
7e07033b10 Merge pull request #892 from Sephster/fix-issue-837
Revert fix for client ID exception
2018-04-21 17:49:42 +01:00
Andrew Millington
6991777ff3 Fix blank line spacing issue 2018-04-20 18:33:46 +01:00
Andrew Millington
9febc32e14 Add spacing around logical blocks 2018-04-20 18:27:47 +01:00
Andrew Millington
c8b44ff5c7 Revert fix for client ID exception 2018-04-20 18:22:07 +01:00
Andrew Millington
9fc288ce53 Merge pull request #876 from steverhoades/fix-example
Fix fatal error in examples caused by ClientRepositoryInterface change
2018-03-17 20:43:53 +00:00
Steve Rhoades
8f1bf88792 Fix fatal error caused by ClientRepositoryInterface change 2018-03-17 09:30:14 -07:00
Andrew Millington
cc19da50b4 Merge pull request #814 from SunMar/master
Allow CryptTrait to accept a \Defuse\Crypto\Key as encryption key #812
2018-02-28 21:12:39 +00:00
Andrew Millington
bec0de16bb Update Changelog 2018-02-28 21:00:30 +00:00
Andrew Millington
a56acc8dd0 Minor code tidy up 2018-02-28 20:33:19 +00:00
Andrew Millington
c9b07f386c Fix StyleCI issues and remove phpdoc order from StyleCI 2018-02-28 20:01:01 +00:00
Andrew Millington
00a7972f74 Merge remote-tracking branch 'upstream/master' 2018-02-28 19:45:41 +00:00
Andrew Millington
e3266cb50a Fix changelog categorisation 2018-02-26 20:08:02 +00:00
Andrew Millington
2fdd6ce494 Add change for access and refresh token emitters 2018-02-26 20:07:02 +00:00
Andrew Millington
6fd3024c48 Merge pull request #860 from Zaszczyk/new-events-to-emitter-#825
Add new event types: access_token_issued and refresh_token_issued.
2018-02-26 20:01:22 +00:00
Andrew Millington
62e06b7d3a Removing Yoda condition
Removed Yoda condition from code base
2018-02-26 19:51:03 +00:00
Simon Hamp
009c109716 TravisCI fix for PHPStan 2018-02-26 16:04:48 +00:00
Simon Hamp
6723aadfe8 Fix #837
Unifies how we fetch the client_id from the request and allows us to throw a more appropriate exception when the client_id parameter is missing.

Improves the test method for this validation by checking the culpable method in this particular case. The test was missing this by calling the wrong method.
2018-02-26 15:56:28 +00:00
Andrew Millington
e24964af07 Update changelog
Add removal of paragone/random_compat to changelog
2018-02-26 12:57:11 +00:00
Andrew Millington
99e42f6f25 Remove paragonie/random_compat
Removing paragonie/random_compat as no longer supporting PHP 5.x branches
2018-02-26 12:38:31 +00:00
Mateusz Błaszczyk
6700b113a8 Add new event types: access_token_issued and refresh_token_issued. 2018-02-23 17:48:51 +01:00
Andrew Millington
28e1418f64 Change to use correct release date for version 7 2018-02-18 20:29:37 +00:00
Lukáš Unger
143afc9561 PHPStan level 7 2018-02-18 21:20:48 +01:00
Andrew Millington
456c6cfdd2 Merge pull request #854 from Sephster/master
Version 7
2018-02-18 15:57:10 +00:00
Andrew Millington
4f68d2a5f2 Fix release tags in changelog 2018-02-18 15:51:41 +00:00
Andrew Millington
49f66866f7 Fix links for versions 6.0.1 - 6.0.2 2018-02-18 15:38:28 +00:00
Andrew Millington
028d91f670 Add code coverage for scrutinizer 2018-02-18 15:33:41 +00:00
Andrew Millington
9287f587fc Update changelog link 2018-02-18 15:29:59 +00:00
Andrew Millington
70396bec67 Chang Changelog format 2018-02-18 15:28:28 +00:00
Andrew Millington
6679418436 Update readme and changelog 2018-02-18 14:20:37 +00:00
Andrew Millington
e04b8f4e6d Merge pull request #744 from erickjth/fix-pkce-implementation
Fix PKCE implementation with strict verifications
2018-02-18 14:10:08 +00:00
Andrew Millington
e0cc5ee1b0 Merge branch 'master' of https://github.com/thephpleague/oauth2-server into fix-pkce-implementation 2018-02-18 13:57:19 +00:00
Andrew Millington
b78c012796 Change code challenge and verifier to be constants in test 2018-02-18 13:51:34 +00:00
Andrew Millington
bcd2fc38c0 Merge pull request #853 from thephpleague/analysis-zGNlb2
Apply fixes from StyleCI
2018-02-17 20:02:03 +00:00
Andrew Millington
25c3c216a0 Apply fixes from StyleCI 2018-02-17 19:31:59 +00:00
Andrew Millington
8bbb20a012 Merge pull request #852 from lookyman/updated-dependencies
Updated dependencies, more strict static analysis
2018-02-17 17:27:58 +00:00
Lukáš Unger
cd5233392e Updated dependencies, more strict static analysis 2018-02-17 18:07:16 +01:00
Andrew Millington
7a6c35bc29 Merge pull request #849 from lookyman/phpunit-version
Update PHPUnit, run static analysis on tests
2018-02-17 16:28:41 +00:00
Andrew Millington
8614aea887 Revert "Remove temp variables and @var comments"
This reverts commit 7a5c511807.
2018-02-17 16:27:41 +00:00
Andrew Millington
7a5c511807 Remove temp variables and @var comments 2018-02-17 16:15:48 +00:00
Andrew Millington
e0b65a2831 Set default mustValidateSecret to true 2018-02-17 11:46:47 +00:00
Andrew Millington
ee7d52ecaa Merge pull request #607 from lucadegasperi/patch-5
Make ClientRepositoryInterface more flexible
2018-02-17 11:42:48 +00:00
Alex Bilbie
7d1d88cdf1 Merge pull request #850 from weirdan/patch-1
Fixed docblock opener
2018-02-12 10:54:26 +00:00
Bruce Weirdan
80a949601f Fixed docblock opener
It's important for tools relying on docblock types to perform static analysis (think phan, phpstan, psalm, etc)
2018-02-12 12:36:59 +02:00
Andrew Millington
fea577f25b Merge pull request #719 from stratoss/stratoss-patch-exeption
Getter and setter for the payload and ability to pass options to json_encode
2018-02-11 22:48:23 +00:00
Lukáš Unger
1f87c7a7be Update PHPUnit, run static analysis on tests 2018-02-11 23:22:46 +01:00
Andrew Millington
3098f6d7fa Merge pull request #839 from simesy/master
Allow other secure key permissions.
2018-02-11 22:17:35 +00:00
Andrew Millington
06a23a1dd0 Update CryptKey.php
Change the error message to reflect that the server will also accept 440 and 400 as a valid file permission
2018-02-11 22:12:55 +00:00
Alex Bilbie
97089ad49e Merge pull request #848 from lookyman/static-analysis
Static analysis with PHPStan
2018-02-11 21:24:52 +00:00
Lukáš Unger
eca385ab08 Static analysis with PHPStan 2018-02-11 22:20:17 +01:00
Andrew Millington
ef06c29ee8 Merge pull request #840 from liverbool/master
BUGFIX: Wrong redirect uri.
2018-02-11 20:20:41 +00:00
Andrew Millington
5fb9fc929a Reinstate check on client redirect URI to fail if multiple redirect URIs have been listed for the client and one has not been specified in the auth request 2018-02-11 20:10:01 +00:00
Andrew Millington
4c548dbd78 Merge pull request #847 from Sephster/master
Minor Coding Standard Fixes
2018-02-11 19:01:12 +00:00
liverbool
b3cd73cac7 code cleaner
cc.

Co-Authored-By: Andrew Millington <sephster@users.noreply.github.com>
2018-02-09 05:54:05 +07:00
Andrew Millington
3999c41fef Merge pull request #845 from kpn13/master
Do not create key file if it already exists and it is the same
2018-02-06 12:32:29 +00:00
Erick Torres
ce2662ece7 Merge branch 'master' of github.com:thephpleague/oauth2-server into fix-pkce-implementation
# Conflicts:
#	tests/Grant/AuthCodeGrantTest.php
2018-02-05 15:32:15 -05:00
Karim PINCHON
d2641b560d Do not create key file if it already exists and it is the same 2018-01-29 11:05:10 +01:00
Andrew Millington
8bbd218856 Merge pull request #842 from sgomez/fix-challenge-pkce
Fix S256 code challenge method
2018-01-25 23:16:15 +00:00
Andrew Millington
eb9cde5ab7 Merge pull request #805 from raarts/Accept-RSA-key-with-crlf-v2
Also accept an RSA key with crlf
2018-01-23 22:24:52 +00:00
Sergio Gómez
1b692e2298 Fix S256 code challenge method
According to [RFC7636#section-4.3](https://tools.ietf.org/html/rfc7636#section-4.3):

    If the "code_challenge_method" from Section 4.3 was "S256", the
    received "code_verifier" is hashed by SHA-256, base64url-encoded, and
    then compared to the "code_challenge", i.e.:

    BASE64URL-ENCODE(SHA256(ASCII(code_verifier))) == code_challenge

So, the hash must be done before the base64_encode.

The tests are modified to use example data from the
[RFC7636#appendix-B](https://tools.ietf.org/html/rfc7636#appendix-B).
2018-01-18 05:31:44 +01:00
liverbool
d22f222e65 BUGFIX: Wrong redirect uri.
This's bugfix when redirect on error.
2018-01-13 11:52:31 +07:00
Simon Hobbs
cf9acb32b8 Allow some more secure options without tsk-tsk. 2018-01-13 15:29:42 +11:00
Alex Bilbie
92d8052a5b Merge pull request #836 from knewzen/master
remove codesponsor
2018-01-04 20:09:23 +00:00
knewzen
a3289c6ecb remove codesponsor 2018-01-05 01:08:14 +08:00
SunMar
292272d128 Allow CryptTrait to accept a \Defuse\Crypto\Key as encryption key #812 2018-01-04 15:14:03 +01:00
Ron Arts
ef8a741527 In public/private keys, force the header to be on its own line, allow missing \n after the footer 2018-01-04 12:17:31 +01:00
Ron Arts
91d9c11fb4 Fixed tests, allow whitespace at the end of a key 2018-01-03 10:18:32 +01:00
Ron Arts
2ec8d148b0 fix .gitattributes 2018-01-03 09:41:39 +01:00
Erick Torres
01d21b2533 Update statement to generate codeChallenge in AuthCodeGrantTest 2017-12-29 12:32:12 -05:00
Andrew Millington
ff29721ca9 Removing call to setEncryptionKey as no such function on the authorization server 2017-12-29 12:29:47 +00:00
Andrew Millington
5b79b40df9 Fixed count placement to make code more efficient as per scrutinizer feedback 2017-12-29 12:25:39 +00:00
Andrew Millington
b6d9835281 Merge branch 'master' into fix-pkce-implementation 2017-12-28 16:37:37 +00:00
Andrew Millington
57ca83a8ba Removing missing scope tests as temporarily reverted this functionality 2017-12-24 00:18:20 +00:00
Andrew Millington
41bba7f58c Removing missing scope test
Temporarily removing missing scope test as have reverted this functionality for version 6.1.1
2017-12-24 00:07:22 +00:00
Andrew Millington
dcae4af6ce Remove missing scope test
Temporarily removing missing scope test for the AuthGrant
2017-12-24 00:06:18 +00:00
Andrew Millington
a0cabb573c Update AbstractGrant.php
Temporarily removing check on empty scopes as causing issues for Passport users
2017-12-23 23:33:42 +00:00
Andrew Millington
276d5b655b Update README.md
Updating readme to refer to the latest 5.1.* branch
2017-12-23 13:20:52 +00:00
Andrew Millington
00138446b6 Merge pull request #828 from Sephster/master
Fixed ordering so we only hash after base64 encoding
2017-12-23 02:14:34 +00:00
Andrew Millington
1c36b70dab Fixed ordering so we only hash after base64 encoding 2017-12-23 02:06:18 +00:00
Andrew Millington
f11e4c81cd Merge pull request #697 from fkooman/fix-s256
Fix PKCE code verifier encoding to match specification
2017-12-23 01:52:33 +00:00
Andrew Millington
f5a1feb67d Added PHP 7.2 to the supported versions 2017-12-13 21:05:36 +00:00
Andrew Millington
1ad4d2121f Merge pull request #822 from carusogabriel/patch-1
Test against PHP 7.2
2017-12-13 21:04:25 +00:00
Andrew Millington
1660dd0559 Merge pull request #824 from carusogabriel/refactoring-tests
Refactoring tests
2017-12-13 21:02:09 +00:00
Gabriel Caruso
9ceafe5dd3 Refactoring tests 2017-12-06 18:24:42 -02:00
Gabriel Caruso
d1d68242ea Test against PHP 7.2 2017-11-30 23:52:50 -02:00
Andrew Millington
a53e753b1a Merge pull request #818 from imanghafoori1/master
flatten code
2017-11-23 22:42:26 +00:00
Iman
f88961eddd flatten code 2017-11-23 21:26:39 +03:30
Andrew Millington
8c93fd74c9 Merge pull request #573 from ismailbaskin/master
Include redirect_uri check on authorization endpoint
2017-11-19 20:57:27 +00:00
Andrew Millington
2765481b9f Handle no scope hint 2017-11-18 18:47:38 +00:00
Andrew Millington
9273936009 Fix bug where not specifying the bad scope 2017-11-18 18:46:03 +00:00
Andrew Millington
5f4ec6a154 Merge pull request #811 from Sephster/master
Add default scopes to authentication server
2017-11-16 19:27:41 +00:00
Sephster
b50c7622db Add in validation for authorization requests.
Fixes thephpleague/oauth2-server#677
2017-11-14 00:12:04 +00:00
Sephster
dc9c1a1023 Remove blank line to keep code consistent 2017-11-13 23:59:55 +00:00
Sephster
6e6baf5b75 Remove abstract authorize grant use 2017-11-13 23:57:24 +00:00
Sephster
7878cf9c13 Merge remote-tracking branch 'upstream/master' 2017-11-13 23:52:36 +00:00
Sephster
1bcee9aaba Add a test for a missing scope for the password grant 2017-11-13 23:16:30 +00:00
Sephster
1e3a84fc85 Add a test to ensure response requests fail without a scope specified 2017-11-13 23:00:27 +00:00
Sephster
a5c5929dc9 Change default scope to be basic 2017-11-13 22:34:12 +00:00
Sephster
c6bf2e1df0 Remove unnecessary white spaces 2017-11-13 22:31:50 +00:00
Sephster
eb645063c7 Reverted the abstract authorise grant to its previous state 2017-11-13 22:25:31 +00:00
Sephster
65789e0f39 Fix tests to support default scopes for authorization requests 2017-11-13 22:20:42 +00:00
Sephster
512d4898e2 Revert previous change 2017-11-13 22:20:16 +00:00
Sephster
c895885700 Modify grants so only auth requests use default scopes 2017-11-13 22:19:44 +00:00
Andrew Millington
661a0994c6 Merge pull request #810 from gabriel-caruso/phpunit
Use PHPUnit\Framework\TestCase instead of PHPUnit_Framework_TestCase
2017-11-08 20:03:08 +00:00
Gabriel Caruso
3871aee48c Bump PHPUnit version for compatibility 2017-11-08 16:20:31 -02:00
Gabriel Caruso
04f3d39b45 Use PHPUnit\Framework\TestCase instead of PHPUnit_Framework_TestCase 2017-11-08 16:07:07 -02:00
Andrew Millington
6bb416ce78 Merge pull request #678 from pcambra/add-zend-diactoros-example
Added Zend diactoros library dependency to the examples
2017-11-07 16:27:26 +00:00
Andrew Millington
ce8248c10f Remove erroneous character 2017-11-06 22:56:54 +00:00
Andrew Millington
13be557825 Re-add the complete testCompleteAuthorizationRequestNoUser() 2017-11-06 22:51:11 +00:00
Andrew Millington
0f08063864 Fixed use of default scope so it is only for authorization requests 2017-11-06 22:33:28 +00:00
Andrew Millington
cc6eb63dd8 Remove default scope from the Refresh Token Grant 2017-11-06 21:23:52 +00:00
Andrew Millington
093c7755fa Remove default scope from the Password Grant 2017-11-06 21:23:14 +00:00
Andrew Millington
82b81c7f6f Remove setDefaultScope function from the grant interface 2017-11-06 21:22:09 +00:00
Andrew Millington
9cd86a9154 Remove default scope for the ClientCredentialsGrant 2017-11-06 21:21:14 +00:00
Andrew Millington
42ea0de9fb Add default scope to the AbstractAuthorizeGrant 2017-11-06 21:19:38 +00:00
Andrew Millington
ab760a805c Remove default scope from abstract grant
This should be added to the AbstractAuthorizeGrant instead as it is 
only used for an authorization request
2017-11-06 21:19:07 +00:00
Andrew Millington
34cb0ba759 Merge branch 'master' into add-zend-diactoros-example 2017-11-05 14:39:01 +00:00
Andrew Millington
ac48653bb5 Merge pull request #797 from thephpleague/Update-Readme
Update readme file to bring in Andy, Brian, and Simon
2017-11-05 11:52:28 +00:00
Andrew Millington
bd2cdaf5da Change missing scope test to check for invalid_scope exception 2017-10-31 23:01:19 +00:00
Andrew Millington
4806eda45a Change to throw invalid scope instead of missing scope exception 2017-10-31 22:59:01 +00:00
Andrew Millington
b2fe909a71 Removed the missing scope exception as should be using invalid_scope 2017-10-31 22:58:07 +00:00
Andrew Millington
d0619385b8 Add a basic test to ensure we throw an exception when no scope is given 2017-10-31 21:00:14 +00:00
Ron Arts
f79d3f27cf Incorporate https://github.com/thephpleague/oauth2-server/pull/731. Thanks.
Now can handle cr/lf, cr, and lf endings. And on php5 large keys as well.
2017-10-31 10:14:46 +01:00
Andrew Millington
3828f87b19 Fix tests as no longer set the default scope in the constructor
Use new setDefaultScope() method instead. Also changed default scope to
be a blank string instead of null
2017-10-30 23:48:02 +00:00
Andrew Millington
a49f6ff80d Remove setting default scope in the constructor 2017-10-30 23:36:19 +00:00
Andrew Millington
1161ceda0d Fix the authorization server middleware test 2017-10-30 23:26:49 +00:00
Andrew Millington
f9143b5163 Fix the refresh token grant test 2017-10-30 23:26:11 +00:00
Ron Arts
90fec63104 Setup the public.key.crlf with the proper permissions 2017-10-30 16:41:10 +01:00
Ron Arts
4563685375 Also accept an RSA key with crlf 2017-10-30 16:21:17 +01:00
Alex Bilbie
cc98b5ec16 Merge pull request #801 from lucasantarella/master
Added ability to specify query delimiter character in the implicit grant
2017-10-28 18:35:22 +07:00
Alex Bilbie
4d77aee4a9 Added a reference to myself§ 2017-10-28 18:29:55 +07:00
Luca Santarella
b6b0e7c944 Merge remote-tracking branch 'origin/master'
# Conflicts:
#	src/Grant/ImplicitGrant.php
2017-10-25 18:34:02 -04:00
Luca Santarella
a4fc05c31e Fixed indentation in comment to match code style 2017-10-25 18:33:54 -04:00
Luca Santarella
606f69e6cd Fixed indentation in comment to match code style 2017-10-25 18:33:26 -04:00
Luca Santarella
825017f27e Ability to specify query delimiter, such as ? instead of the hard-coded # 2017-10-25 18:30:17 -04:00
Colin O'Dell
37645f3244 Merge pull request #796 from thephpleague/analysis-8mEDjY
Apply fixes from StyleCI
2017-10-23 15:44:37 -04:00
Brian Retterer
63c2c21ee6 Update readme file to bring in Andy, Brian, and Simon 2017-10-23 11:26:21 -04:00
Brian Retterer
23c7138d48 Apply fixes from StyleCI 2017-10-23 15:26:10 +00:00
Andrew Millington
63861704b6 Merge pull request #749 from dmelo/issue-748
Replaces array_key_exists by isset, which is faster, on ImplicitGrant.
2017-10-20 18:28:18 +01:00
Diogo Oliveira de Melo
203be5ca20 Revert comparison order, as suggested by @Sephster 2017-10-20 09:23:36 -02:00
Andrew Millington
24f29b6382 Fix more tests to support default scope setting 2017-10-19 22:37:19 +01:00
Andrew Millington
8c788e9fc8 Update tests so they don't trigger missing or invalid scope exceptions 2017-10-18 22:11:13 +01:00
Andrew Millington
4d28eadf93 Update tests so they don't trigger missing or invalid scope exceptions 2017-10-18 22:11:02 +01:00
Andrew Millington
5a28fb8af4 Set a default scope for the authorization server 2017-10-18 22:09:53 +01:00
Andrew Millington
c996b66528 Add means to set default scopes for grants 2017-10-18 22:08:41 +01:00
Andrew Millington
c70451abd5 Add an exception for a missing scope 2017-10-18 22:08:11 +01:00
Andrew Millington
e7ee483d11 Changed function comment to reflect we are setting the public, instead of private key 2017-10-13 23:02:29 +01:00
Alex Bilbie
5b223a9501 Update README.md 2017-10-11 10:33:10 +01:00
Erick Torres
4270f5bac1 Merge branch 'master' of github.com:erickjth/oauth2-server into fix-pkce-implementation
# Conflicts:
#	src/Grant/AuthCodeGrant.php
2017-09-07 17:24:48 -05:00
Alex Bilbie
3b58ab1df2 Merge pull request #724 from davedevelopment/change-token-type-case
Change case for implict grant token_type
2017-08-11 08:16:08 +01:00
Alex Bilbie
925776958f Updated changelog 2017-08-03 16:09:23 +01:00
Alex Bilbie
c86c7dde70 Fix #759 2017-08-03 16:07:11 +01:00
Alex Bilbie
e184691ded Merge pull request #776 from yannickl88/fix/perm-key-check
Removed chmod from CryptKey and add toggle to disable checking
2017-08-03 16:04:08 +01:00
Alex Bilbie
b2648218f1 Merge pull request #777 from hhamon/hhamon-patch-1
[BC Break] Fixes invalid code challenge method payload key name
2017-08-03 16:03:48 +01:00
Yannick de Lange
2aca909d20 Removed chmod from CryptKey and add toggle to disable checking 2017-08-03 15:57:39 +02:00
Hugo Hamon
79038ced78 [BC Break] Fixes invalid code challenge method payload key name
I guess this change might be a BC break for existing and active authorization tokens when they're validated by the server. The good thing is that an authorization token has a very short expiration time and is used once to request an access token.
2017-08-02 17:55:11 +02:00
Alex Bilbie
7c2218fdcc Merge pull request #773 from kumy/issue-772
Fix #772 - PR should be based on master branch
2017-07-30 08:32:30 +01:00
Alex Bilbie
935fff8308 Merge pull request #770 from benito103e/master
Updated PHPDoc about the unicity violation exception throwing
2017-07-30 08:31:50 +01:00
Mathieu Alorent
0f1ddaaacf Fix #772 - PR should be based on master branch 2017-07-29 17:41:44 +02:00
Benjamin Dieleman
ecc07abb33 Updated PHPDoc about the unicity violation exception throwing
UniqueTokenIdentifierConstraintViolationException can be thrown when persisting tokens
2017-07-27 17:31:01 +02:00
Alex Bilbie
a1b8d87b47 Updated changelog 2017-07-19 07:58:56 +01:00
Alex Bilbie
80fc8e654b Trigger E_USER_NOTICE instead of throwing an exception if key cannot be chmod to 600 2017-07-19 07:57:47 +01:00
Erick Torres
88ccb6ff13 Fix codeVerifier check. Keep code style. 2017-07-07 12:35:42 -05:00
Erick Torres
e2f9b73df3 Fix broken tests 2017-07-07 12:19:11 -05:00
Erick Torres
fbb3586cae Merge branch 'master' of github.com:erickjth/oauth2-server into fix-pkce-implementation
# Conflicts:
#	src/Grant/AuthCodeGrant.php
#	tests/Grant/AuthCodeGrantTest.php
2017-07-07 12:06:32 -05:00
Alex Bilbie
317f46b7ae Merge pull request #754 from Lctrs/fix/missing-sprintf
Fix missing sprintf() calls
2017-07-07 16:50:08 +01:00
Jérôme Parmentier
88bf8b2367 Fix missing sprintf 2017-07-03 20:28:28 +02:00
Alex Bilbie
315d079033 Added link to security release information page 2017-07-02 18:44:55 +01:00
Alex Bilbie
2824f7d27e Fixed examples 2017-07-01 18:46:48 +01:00
Alex Bilbie
0a6a4deca6 5.1.4 not 5.1.14 2017-07-01 18:38:35 +01:00
Alex Bilbie
00c645545a Updated changelog 2017-07-01 18:33:17 +01:00
Alex Bilbie
417a64ad43 Added security notice 2017-07-01 18:33:03 +01:00
Alex Bilbie
f5c3ba0b24 Removed dead code 2017-07-01 18:22:51 +01:00
Alex Bilbie
e1ef133067 Dropped PHP 5.5 compatability 2017-07-01 18:22:44 +01:00
Alex Bilbie
523434902c Removed dead code 2017-07-01 18:15:41 +01:00
Alex Bilbie
aac467e616 Fixed broken tests 2017-07-01 18:11:19 +01:00
Alex Bilbie
76c2b6f88c AuthorizationServer no longer needs to know about the public key 2017-07-01 18:11:10 +01:00
Alex Bilbie
72349ef22f Encryption key is now always required so remove redundent code 2017-07-01 18:10:53 +01:00
Alex Bilbie
850793ab88 Added missing methods 2017-07-01 18:08:49 +01:00
Alex Bilbie
0f73bf0054 Encryption key just uses Defuse\Crypto now, no key based crypto 2017-07-01 18:07:51 +01:00
Alex Bilbie
7953f27b38 Stop testing HHVM 2017-07-01 18:07:09 +01:00
Alex Bilbie
cc2c3a7044 Removed unnecessary stuff from composer.json 2017-07-01 18:07:01 +01:00
Alex Bilbie
06424fdbe2 Use Trusty for TravisCI 2017-07-01 17:24:11 +01:00
Alex Bilbie
55f93f9400 Merge pull request #752 from thephpleague/analysis-qBDGNm
Apply fixes from StyleCI
2017-07-01 17:20:19 +01:00
Alex Bilbie
aee1779432 Apply fixes from StyleCI 2017-07-01 16:19:23 +00:00
Alex Bilbie
09c167ac43 Updated changelog and readme 2017-07-01 17:17:55 +01:00
Alex Bilbie
765a01021b Updated error message 2017-07-01 16:45:29 +01:00
Alex Bilbie
0706d66c76 Don’t pad and shuffle the payload if an encryption key has been set 2017-07-01 16:45:29 +01:00
Alex Bilbie
e123fe82d0 Ignore error_log messages in code coverage 2017-07-01 16:45:29 +01:00
Alex Bilbie
107cfc3678 Updated examples 2017-07-01 16:45:29 +01:00
Alex Bilbie
1954120c3d Use catch all exception 2017-07-01 16:45:29 +01:00
Alex Bilbie
dd5eee150d Ensure response type also has access to the encryption key 2017-07-01 16:45:29 +01:00
Alex Bilbie
76c1349181 Updated random_compat version 2017-07-01 16:45:29 +01:00
Alex Bilbie
1af4012df4 New property on AuthorizationServer to receive an encryption key which is used for future encryption/decryption instead of keybased encryption/decryption 2017-07-01 16:45:29 +01:00
Alex Bilbie
4a717104fa Shuffle the contents of the authorization code payload 2017-07-01 16:45:29 +01:00
Alex Bilbie
63530443fe Better error checking when saving a temporary key to ensure file was written successfully and the server is the exclusive mode 2017-07-01 16:44:57 +01:00
Alex Bilbie
2f8de3d230 Ensure the server is the exclusive owner of the key 2017-07-01 16:44:51 +01:00
Alex Bilbie
57d199b889 Stricter validation of code challenge value to match RFC 7636 requirements 2017-07-01 16:44:43 +01:00
Alex Bilbie
6bdd108145 Escape scope parameter to reduce pontential XSS vector 2017-07-01 16:43:31 +01:00
Diogo Oliveira de Melo
170ce2fd2d Replaces array_key_exists by isset, which is faster, on ImplicitGrant. 2017-06-30 15:42:23 -03:00
Erick Torres
4710743b87 Add "dist: trusty" into travis setting file 2017-06-16 17:09:13 -05:00
Erick Torres
11ad87b5f5 Update tests / Add missing. 2017-06-16 12:03:14 -05:00
Erick Torres
880e3b4590 Fix invalid code_challenge_method key. 2017-06-16 12:03:04 -05:00
Erick Torres
2167edf1d9 Validate codeVerifier and codeChallenge correctly. 2017-06-16 12:02:48 -05:00
Erick Torres
2482630221 Fix codeVerifier hash verification. 2017-06-16 12:02:34 -05:00
Dave Marshall
83228bdcd5 Change case for implict grant token_type 2017-03-27 12:11:25 +01:00
Stanimir Stoyanov
d73b15ae32 Getter and setter for the payload and ability to pass options to json_encode 2017-03-20 14:52:35 +02:00
Stanimir Stoyanov
945624eb51 Merge pull request #1 from thephpleague/master
Merging changes into my fork
2017-03-17 19:36:34 +02:00
Alex Bilbie
bf7084a147 Merge pull request #709 from toby-griffiths/fix-refresh-token-ttl
Corrected DateInterval from 1 min to 1 month
2017-03-02 14:06:27 +00:00
Toby Griffiths
13c608b849 Corrected DateInterval from 1 min to 1 month 2017-03-01 13:08:42 +00:00
Ian Littman
d8ece093d5 Add hasRedirect() method for OAuthServerException
Resolves #694.
2017-02-04 14:50:46 -05:00
Alex Bilbie
ded7c1ed47 Mentioned PHP 7.1 support 2017-02-02 17:29:06 +00:00
François Kooman
6426e597a3 Fix PKCE code verifier encoding to match specification
The current implementation of PKCE does not follow the specification
correctly regarding the encoding of the code verifier. This patch
correctly encodes the hash of the code verifier according to
Appenix A of RFC 7636.
2017-01-24 11:36:34 +01:00
Alex Bilbie
0da70c916a Merge pull request #690 from Jalle19/patch-1
Fix typo in the first README sentence
2016-12-23 07:42:23 +00:00
Sam Stenvall
90cb1bf012 Fix typo in the first README sentence 2016-12-23 00:30:54 +02:00
Alex Bilbie
b32204bd91 Merge pull request #682 from wilsonge/patch-1
Fix middleware example fatal error
2016-11-08 13:18:13 +00:00
George Wilson
518c1fcec5 Fix middleware example fatal error 2016-11-08 12:27:49 +00:00
Pedro Cambra
ee8841fe66 Added Zend diactoros library dependency to the examples 2016-10-31 09:57:44 +09:00
Alex Bilbie
6946592553 Merge pull request #671 from duncan3dc/patch-1
[Travis] Test on PHP 7.1
2016-10-16 16:58:15 +01:00
Craig Duncan
25580b98b7 [Travis] Test on PHP 7.1 2016-10-16 16:48:44 +01:00
Alex Bilbie
f78dc2eca0 Updated README 2016-10-12 15:08:15 +01:00
Alex Bilbie
105b3116dc Merge pull request #669 from jeremykendall/fix/www-authenticate-header
Fix WWW-Authenticate entry in $headers array
2016-10-12 15:05:19 +01:00
jeremykendall
01677a564e Fix WWW-Authenticate entry in $headers array
In this context the header name should be the array key and the header
value the array value.
2016-10-11 22:27:24 -05:00
Alex Bilbie
4c4b0633b1 Merge pull request #668 from er0k/increase-ssl-key-length
Increase the recommended RSA key length from 1024 to 2048 bits
2016-10-11 14:27:16 +01:00
er0k
c4a75b2880 Increase the recommended RSA key length from 1024 to 2048 bits 2016-10-11 09:24:27 -04:00
Alex Bilbie
e091d48127 Changelog bump 2016-09-19 10:23:42 +01:00
Alex Bilbie
a798cfdc5d Merge pull request #656 from thephpleague/issue-650-fix
Fix for #650
2016-09-19 10:19:05 +01:00
Alex Bilbie
56e8d374fb Fix broken tests 2016-09-19 10:06:00 +01:00
Alex Bilbie
b1bfff7325 Don't pass in user because we don't know who user is 2016-09-19 10:05:55 +01:00
Alex Bilbie
32cde01ab2 Merge pull request #657 from thephpleague/analysis-86wPg4
Applied fixes from StyleCI
2016-09-13 15:19:56 +01:00
Alex Bilbie
11ccc305d0 Applied fixes from StyleCI 2016-09-13 14:17:09 +00:00
Alex Bilbie
d7df2f7e24 Fix for #650 2016-09-13 15:16:58 +01:00
Alex Bilbie
b8b92e5925 Changelog update 2016-07-26 15:42:03 -04:00
Alex Bilbie
0ebdcd2ab8 Merge pull request #614 from lookyman/better-tests
Improved tests
2016-07-25 12:17:28 -04:00
Alex Bilbie
9dee08ba3d Merge pull request #625 from juliangut/key-file
Key file auto-generation from string
2016-07-19 17:24:12 +01:00
Julián Gutiérrez
065ef5db99 CryptKey tests 2016-07-19 17:15:36 +02:00
Julián Gutiérrez
039537ebe2 touch! 2016-07-19 15:06:32 +02:00
Julián Gutiérrez
d8930af5ee key file auto-generation from string 2016-07-19 15:01:31 +02:00
Alex Bilbie
ada8d20be6 Merge pull request #624 from iansltx/bearer-token-response-params
Allow easy addition of custom fields to Bearer token response
2016-07-16 16:38:23 +01:00
Ian Littman
090c01d3d1 Allow easy addition of custom fields to Bearer token response 2016-07-16 10:27:33 -05:00
Alex Bilbie
4b6ba5859c Merge pull request #621 from pounard/master
while(array_shift()) makes the AuthorizationServer class configuratio…
2016-07-13 11:02:26 +01:00
Pierre Rineau
57323f38f7 while(array_shift()) makes the AuthorizationServer class configuration mutable 2016-07-13 12:03:05 +02:00
Alex Bilbie
46cd448a47 Merge pull request #616 from lookyman/phpdoc
Updated PHPDoc
2016-07-10 09:32:13 +01:00
Lukáš Unger
c874c59b9c Explicitly compare to false when checking not instanceof 2016-07-09 12:09:21 +02:00
Lukáš Unger
c3a4670c11 Updated PHPDoc 2016-07-09 02:01:53 +02:00
Lukáš Unger
17b6e2a207 tests: Fix missing redirect uri test, add redirect uri mismatch test 2016-07-08 16:04:14 +02:00
Lukáš Unger
54422a244f tests: AuthCodeGrantTest additional tests 2016-07-08 15:31:29 +02:00
Lukáš Unger
9899aa1f99 tests: ImplicitGrantTest additional tests 2016-07-08 15:30:59 +02:00
Lukáš Unger
32efd091a1 tests: use MockBuilder everywhere 2016-07-08 15:29:21 +02:00
Luca Degasperi
655a4b2715 Make ClientRepositoryInterface more flexible
This small change will allow the use of the ```ClientRepositoryInterface``` for more use cases than simply validating clients when authorizing them. There might be some places where this change will affect the behavior. I also think the ```$mustValidateSecret``` is redundant since in an implementation a check could be done wether ```$clientSecret``` is null or not.
2016-06-30 16:49:47 +02:00
Alex Bilbie
68e4b1d390 Updated changelog 2016-06-28 09:03:41 +01:00
Alex Bilbie
5ee1583c5b Ensure state is in access denied redirect. Fixes #597 2016-06-28 09:03:01 +01:00
Alex Bilbie
66de05a395 Merge pull request #605 from jfilla/master
Added catch Runtime exception when parsing JWT string
2016-06-28 08:49:29 +01:00
Alex Bilbie
df20da1235 Merge pull request #601 from zerkms/ISSUE-596_UNIQUE_ACCESS_TOKEN
Added a check for unique access token constraint violation
2016-06-28 08:48:38 +01:00
Alex Bilbie
7321622104 Merge pull request #606 from GrahamCampbell/patch-2
Allow random compat 2.x
2016-06-28 08:46:57 +01:00
Graham Campbell
84187041bd Allow random compat 2.x 2016-06-27 19:31:35 +01:00
Jakub Filla
9eccc40eb6 Added catch Runtime exception when parsing JWT string 2016-06-22 12:38:03 +02:00
Alex Bilbie
8b865cc523 Merge pull request #604 from iansltx/http-basic-from-header
Look at Authorization header directly for HTTP Basic auth checks
2016-06-22 08:42:30 +01:00
Ian Littman
9775c0076b Look at Authorization header directly for HTTP Basic auth check
Should allow for better compatibility with server implementations that aren't sitting on top of a standard SAPI (e.g. persistent web servers building a PSR-7 compatible request from a socket-received message).

One catch here is that I've seen Apache hijack the HTTP Authorization header in the past, though that would probably impact the other aspects of the server just as much as it would this, so I think that risk is manageable.

Added tests to cover all paths through the new code, so the AbstractGrant type still has 100% coverage :)

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

19
.gitattributes vendored
View File

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

20
.gitignore vendored
View File

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

View File

@@ -2,7 +2,6 @@ filter:
excluded_paths:
- tests/*
- vendor/*
- examples/*
checks:
php:
code_rating: true

52
.styleci.yml Normal file
View File

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

View File

@@ -1,56 +1,32 @@
language: php
dist: trusty
sudo: false
cache:
directories:
- vendor
- vendor
env:
- DEPENDENCIES=""
- DEPENDENCIES="--prefer-lowest --prefer-stable"
php:
- 5.4
- 5.5
- 5.6
- 7.0
- hhvm
matrix:
allow_failures:
- php: 7.0
fast_finish: true
- 7.1
- 7.2
- 7.3
install:
- travis_retry composer install --no-interaction --prefer-source
- composer update --no-interaction --prefer-dist $DEPENDENCIES
script:
- mkdir -p build/logs
- phpunit --coverage-text --verbose --coverage-clover=coverage.clover --coverage-html coverage
- vendor/bin/phpunit --coverage-clover=coverage.clover
- vendor/bin/phpstan analyse -l 7 -c phpstan.neon src tests
after_script:
- bash -c 'if [ "$TRAVIS_PHP_VERSION" == "5.6" ]; then wget https://scrutinizer-ci.com/ocular.phar; fi;
- bash -c 'if [ "$TRAVIS_PHP_VERSION" == "5.6" ]; then php ocular.phar code-coverage:upload --format=php-clover coverage.clover; fi;
- git config --global user.email "travis@travis-ci.org"
- git config --global user.name "TravisCI"
- cp -R coverage ${HOME}/coverage
- cd ${HOME}
- git clone --quiet --branch=gh-pages https://${GITHUBTOKEN}@github.com/thephpleague/oauth2-server.git gh-pages > /dev/null
- cd gh-pages
- mkdir ${TRAVIS_BRANCH}
- cd ${TRAVIS_BRANCH}
- cp -Rf $HOME/coverage/* .
- git add -f .
- git commit -m "Travis pushed coverage of ${TRAVIS_COMMIT}@${TRAVIS_BRANCH} to gh-pages"
- git push -fq origin gh-pages > /dev/null
- wget https://scrutinizer-ci.com/ocular.phar
- php ocular.phar code-coverage:upload --format=php-clover coverage.clover
branches:
only:
- master
env:
global:
secure: "C4wD/BQefKSu9W594iyLp+IBCjlM8kKlmp+nXKXnZGi0L8IkV3m4mmNOb8PExxGMhZ3mlev5DnU4Uoh4oJaUxnkR1FpX4dSEpyzU3VknUzSE2yZOlL+bdCw3o85TGoCcp/+ReJCOw5sncxTskJKHlW1YMa33FznaXwLNoImpjTg="
notifications:
webhooks:
urls:
- https://webhooks.gitter.im/e/7de0ca12596cd5268f30
on_success: always # options: [always|never|change] default: always
on_failure: always # options: [always|never|change] default: always
on_start: false # default: false

View File

@@ -1,201 +1,535 @@
# Changelog
All notable changes to this project will be documented in this file.
## 4.1.5 (released 2016-01-04)
The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
* Enable Symfony 3.0 support (#412)
## [Unreleased]
## 4.1.4 (released 2015-11-13)
### Fixed
- Clients are now explicitly prevented from using the Client Credentials grant unless they are confidential to conform
with the OAuth2 spec (PR #1035)
* Fix for determining access token in header (Issue #328)
* Refresh tokens are now returned for MAC responses (Issue #356)
* Added integration list to readme (Issue #341)
* Expose parameter passed to exceptions (Issue #345)
* Removed duplicate routing setup code (Issue #346)
* Docs fix (Issues #347, #360, #380)
* Examples fix (Issues #348, #358)
* Fix typo in docblock (Issue #352)
* Improved timeouts for MAC tokens (Issue #364)
* `hash_hmac()` should output raw binary data, not hexits (Issue #370)
* Improved regex for matching all Base64 characters (Issue #371)
* Fix incorrect signature parameter (Issue #372)
* AuthCodeGrant and RefreshTokenGrant don't require client_secret (Issue #377)
* Added priority argument to event listener (Issue #388)
## [8.0.0] - released 2019-07-13
## 4.1.3 (released 2015-03-22)
### Added
- Flag, `requireCodeChallengeForPublicClients`, used to reject public clients that do not provide a code challenge for the Auth Code Grant; use AuthCodeGrant::disableRequireCodeCallengeForPublicClients() to turn off this requirement (PR #938)
- Public clients can now use the Auth Code Grant (PR #938)
- `isConfidential` getter added to `ClientEntity` to identify type of client (PR #938)
- Function `validateClient()` added to validate clients which was previously performed by the `getClientEntity()` function (PR #938)
- Add a new function to the AbstractGrant class called `getClientEntityOrFail()`. This is a wrapper around the `getClientEntity()` function that ensures we emit and throw an exception if the repo doesn't return a client entity. (PR #1010)
* Docblock, namespace and inconsistency fixes (Issue #303)
* Docblock type fix (Issue #310)
* Example bug fix (Issue #300)
* Updated league/event to ~2.1 (Issue #311)
* Fixed missing session scope (Issue #319)
* Updated interface docs (Issue #323)
* `.travis.yml` updates
### Changed
- Replace `convertToJWT()` interface with a more generic `__toString()` to improve extensibility; AccessTokenEntityInterface now requires `setPrivateKey(CryptKey $privateKey)` so `__toString()` has everything it needs to work (PR #874)
- The `invalidClient()` function accepts a PSR-7 compliant `$serverRequest` argument to avoid accessing the `$_SERVER` global variable and improve testing (PR #899)
- `issueAccessToken()` in the Abstract Grant no longer sets access token client, user ID or scopes. These values should already have been set when calling `getNewToken()` (PR #919)
- No longer need to enable PKCE with `enableCodeExchangeProof` flag. Any client sending a code challenge will initiate PKCE checks. (PR #938)
- Function `getClientEntity()` no longer performs client validation (PR #938)
- Password Grant now returns an invalid_grant error instead of invalid_credentials if a user cannot be validated (PR #967)
- Use `DateTimeImmutable()` instead of `DateTime()`, `time()` instead of `(new DateTime())->getTimeStamp()`, and `DateTime::getTimeStamp()` instead of `DateTime::format('U')` (PR #963)
## 4.1.2 (released 2015-01-01)
### Removed
- `enableCodeExchangeProof` flag (PR #938)
- Support for PHP 7.0 (PR #1014)
- Remove JTI claim from JWT header (PR #1031)
* Remove side-effects in hash_equals() implementation (Issue #290)
## [7.4.0] - released 2019-05-05
## 4.1.1 (released 2014-12-31)
### Changed
- RefreshTokenRepository can now return null, allowing refresh tokens to be optional. (PR #649)
* Changed `symfony/http-foundation` dependency version to `~2.4` so package can be installed in Laravel `4.1.*`
## [7.3.3] - released 2019-03-29
## 4.1.0 (released 2014-12-27)
### Added
- Added `error_description` to the error payload to improve standards compliance. The contents of this are copied from the existing `message` value. (PR #1006)
* Added MAC token support (Issue #158)
* Fixed example init code (Issue #280)
* Toggle refresh token rotation (Issue #286)
* Docblock fixes
### Deprecated
- Error payload will not issue `message` value in the next major release (PR #1006)
## 4.0.5 (released 2014-12-15)
## [7.3.2] - released 2018-11-21
* Prevent duplicate session in auth code grant (Issue #282)
### Fixed
- Revert setting keys on response type to be inside `getResponseType()` function instead of AuthorizationServer constructor (PR #969)
## 4.0.4 (released 2014-12-03)
## [7.3.1] - released 2018-11-15
* Ensure refresh token hasn't expired (Issue #270)
### Fixed
- Fix issue with previous release where interface had changed for the AuthorizationServer. Reverted to the previous interface while maintaining functionality changes (PR #970)
## 4.0.3 (released 2014-12-02)
## [7.3.0] - released 2018-11-13
* Fix bad type hintings (Issue #267)
* Do not forget to set the expire time (Issue #268)
### Changed
- Moved the `finalizeScopes()` call from `validateAuthorizationRequest` method to the `completeAuthorizationRequest` method so it is called just before the access token is issued (PR #923)
## 4.0.2 (released 2014-11-21)
### Added
- Added a ScopeTrait to provide an implementation for jsonSerialize (PR #952)
- Ability to nest exceptions (PR #965)
* Improved interfaces (Issue #255)
* Learnt how to spell delimiter and so `getScopeDelimiter()` and `setScopeDelimiter()` methods have been renamed
* Docblock improvements (Issue #254)
### Fixed
- Fix issue where AuthorizationServer is not stateless as ResponseType could store state of a previous request (PR #960)
## 4.0.1 (released 2014-11-09)
## [7.2.0] - released 2018-06-23
* Alias the master branch in composer.json (Issue #243)
* Numerous PHP CodeSniffer fixes (Issue #244)
* .travis.yml update (Issue #245)
* The getAccessToken method should return an AccessTokenEntity object instead of a string in ResourceServer.php (#246)
### Changed
- Added new`validateRedirectUri` method AbstractGrant to remove three instances of code duplication (PR #912)
- Allow 640 as a crypt key file permission (PR #917)
## 4.0.0 (released 2014-11-08)
### Added
- Function `hasRedirect()` added to `OAuthServerException` (PR #703)
* Complete rewrite
* Check out the documentation - [http://oauth2.thephpleague.com](http://oauth2.thephpleague.com)
### Fixed
- Catch and handle `BadMethodCallException` from the `verify()` method of the JWT token in the `validateAuthorization` method (PR #904)
## 3.2.0 (released 2014-04-16)
## [4.1.7] - released 2018-06-23
* Added the ability to change the algorithm that is used to generate the token strings (Issue #151)
### Fixed
- Ensure `empty()` function call only contains variable to be compatible with PHP 5.4 (PR #918)
## 3.1.2 (released 2014-02-26)
## [7.1.1] - released 2018-05-21
* Support Authorization being an environment variable. [See more](http://fortrabbit.com/docs/essentials/quirks-and-constraints#authorization-header)
### Fixed
- No longer set a WWW-Authenticate header for invalid clients if the client did not send an Authorization header in the original request (PR #902)
## 3.1.1 (released 2013-12-05)
## [7.1.0] - released 2018-04-22
* Normalize headers when `getallheaders()` is available (Issues #108 and #114)
### Changed
- Changed hint for unsupportedGrantType exception so it no longer references the grant type parameter which isn't always expected (PR #893)
- Upgrade PHPStan checks to level 7 (PR #856)
## 3.1.0 (released 2013-12-05)
### Added
- Added event emitters for issued access and refresh tokens (PR #860)
- Can now use Defuse\Crypto\Key for encryption/decryption of keys which is faster than the Cryto class (PR #812)
* No longer necessary to inject the authorisation server into a grant, the server will inject itself
* Added test for 1419ba8cdcf18dd034c8db9f7de86a2594b68605
### Removed
- Remove paragone/random_compat from dependencies
## 3.0.1 (released 2013-12-02)
## [7.0.0] - released 2018-02-18
* Forgot to tell TravisCI from testing PHP 5.3
### Added
- Use PHPStan for static analysis of code (PR #848)
- Enforce stricter static analysis checks and upgrade library dependencies (PR #852)
- Provide PHPStan coverage for tests and update PHPUnit (PR #849)
- Get and set methods for OAuth Server Exception payloads. Allow implementer to specify the JSON encode options (PR #719)
## 3.0.0 (released 2013-12-02)
### Changed
- ClientRepository interface will now accept null for the Grant type to improve extensibility options (PR #607)
- Do not issue an error if key file permissions are 400 or 440 (PR #839)
- Skip key file creation if the file already exists (PR #845)
- Change changelog format and update readme
* Fixed spelling of Implicit grant class (Issue #84)
* Travis CI now tests for PHP 5.5
* Fixes for checking headers for resource server (Issues #79 and #)
* The word "bearer" now has a capital "B" in JSON output to match OAuth 2.0 spec
* All grants no longer remove old sessions by default
* All grants now support custom access token TTL (Issue #92)
* All methods which didn't before return a value now return `$this` to support method chaining
* Removed the build in DB providers - these will be put in their own repos to remove baggage in the main repository
* Removed support for PHP 5.3 because this library now uses traits and will use other modern PHP features going forward
* Moved some grant related functions into a trait to reduce duplicate code
### Removed
- Support for PHP 5.6
- Support for version 5.x and 6.x of the library
## 2.1.1 (released 2013-06-02)
### Fixed
- PKCE implementation (PR #744)
- Set correct redirect URI when validating scopes (PR #840)
- S256 code challenege method (PR #842)
- Accept RSA key with CRLF line endings (PR #805)
* Added conditional `isValid()` flag to check for Authorization header only (thanks @alexmcroberts)
* Fixed semantic meaning of `requireScopeParam()` and `requireStateParam()` by changing their default value to true
* Updated some duff docblocks
* Corrected array key call in Resource.php (Issue #63)
## [6.1.1] - 2017-12-23
## 2.1 (released 2013-05-10)
- Removed check on empty scopes
* Moved zetacomponents/database to "suggest" in composer.json. If you rely on this feature you now need to include " zetacomponents/database" into "require" key in your own composer.json. (Issue #51)
* New method in Refresh grant called `rotateRefreshTokens()`. Pass in `true` to issue a new refresh token each time an access token is refreshed. This parameter needs to be set to true in order to request reduced scopes with the new access token. (Issue #47)
* Rename `key` column in oauth_scopes table to `scope` as `key` is a reserved SQL word. (Issue #45)
* The `scope` parameter is no longer required by default as per the RFC. (Issue #43)
* You can now set multiple default scopes by passing an array into `setDefaultScope()`. (Issue #42)
* The password and client credentials grants now allow for multiple sessions per user. (Issue #32)
* Scopes associated to authorization codes are not held in their own table (Issue #44)
* Database schema updates.
## [6.1.0] - 2017-12-23
## 2.0.5 (released 2013-05-09)
- Changed the token type issued by the Implicit Grant to be Bearer instead of bearer. (PR #724)
- Replaced call to array_key_exists() with the faster isset() on the Implicit Grant. (PR #749)
- Allow specification of query delimiter character in the Password Grant (PR #801)
- Add Zend Diactoros library dependency to examples (PR #678)
- Can set default scope for the authorization endpoint. If no scope is passed during an authorization request, the default scope will be used if set. If not, the server will issue an invalid scope exception (PR #811)
- Added validation for redirect URIs on the authorization end point to ensure exactly one redirection URI has been passed (PR #573)
* Fixed `oauth_session_token_scopes` table primary key
* Removed `DEFAULT ''` that has slipped into some tables
* Fixed docblock for `SessionInterface::associateRefreshToken()`
## [6.0.2] - 2017-08-03
## 2.0.4 (released 2013-05-09)
- An invalid refresh token that can't be decrypted now returns a HTTP 401 error instead of HTTP 400 (Issue #759)
- Removed chmod from CryptKey and add toggle to disable checking (Issue #776)
- Fixes invalid code challenge method payload key name (Issue #777)
* Renamed primary key in oauth_client_endpoints table
* Adding missing column to oauth_session_authcodes
* SECURITY FIX: A refresh token should be bound to a client ID
## [6.0.1] - 2017-07-19
## 2.0.3 (released 2013-05-08)
To address feedback from the security release the following change has been made:
* Fixed a link to code in composer.json
- If an RSA key cannot be chmod'ed to 600 then it will now throw a E_USER_NOTICE instead of an exception.
## 2.0.2 (released 2013-05-08)
## [6.0.0] - 2017-07-01
* Updated README with wiki guides
* Removed `null` as default parameters in some methods in the storage interfaces
* Fixed license copyright
- Breaking change: The `AuthorizationServer` constructor now expects an encryption key string instead of a public key
- Remove support for HHVM
- Remove support for PHP 5.5
## 2.0.0 (released 2013-05-08)
## [5.1.4] - 2017-07-01
- Fixed multiple security vulnerabilities as a result of a security audit paid for by the [Mozilla Secure Open Source Fund](https://wiki.mozilla.org/MOSS/Secure_Open_Source). All users of this library are encouraged to update as soon as possible to this version or version 6.0 or greater.
- It is recommended on each `AuthorizationServer` instance you set the `setEncryptionKey()`. This will result in stronger encryption being used. If this method is not set messages will be sent to the defined error handling routines (using `error_log`). Please see the examples and documentation for examples.
- TravisCI now tests PHP 7.1 (Issue #671)
- Fix middleware example fatal error (Issue #682)
- Fix typo in the first README sentence (Issue #690)
- Corrected DateInterval from 1 min to 1 month (Issue #709)
## [5.1.3] - 2016-10-12
- Fixed WWW-Authenticate header (Issue #669)
- Increase the recommended RSA key length from 1024 to 2048 bits (Issue #668)
## [5.1.2] - 2016-09-19
- Fixed `finalizeScopes` call (Issue #650)
## [4.1.6] - 2016-09-13
- Less restrictive on Authorization header check (Issue #652)
## [5.1.1] - 2016-07-26
- Improved test suite (Issue #614)
- Updated docblocks (Issue #616)
- Replace `array_shift` with `foreach` loop (Issue #621)
- Allow easy addition of custom fields to Bearer token response (Issue #624)
- Key file auto-generation from string (Issue #625)
## [5.1.0] - 2016-06-28
- Implemented RFC7636 (Issue #574)
- Unify middleware exception responses (Issue #578)
- Updated examples (Issue #589)
- Ensure state is in access denied redirect (Issue #597)
- Remove redundant `isExpired()` method from entity interfaces and traits (Issue #600)
- Added a check for unique access token constraint violation (Issue #601)
- Look at Authorization header directly for HTTP Basic auth checks (Issue #604)
- Added catch Runtime exception when parsing JWT string (Issue #605)
- Allow `paragonie/random_compat` 2.x (Issue #606)
- Added `indigophp/hash-compat` to Composer suggestions and `require-dev` for PHP 5.5 support
## [5.0.3] - 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] - 2016-04-18
- `state` parameter is now correctly returned after implicit grant authorization
- Small code and docblock improvements
## [5.0.1] - 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] - 2016-04-17
Version 5 is a complete code rewrite.
- 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] - 2016-04-10
- 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] - 2016-03-24
Version 5 is a complete code rewrite.
- JWT support
- PSR-7 support
- Improved exception errors
- Replace all occurrences of the term "Storage" with "Repository"
- Simplify repositories
- Entities conform to interfaces and use traits
- Auth code grant updated
- Allow support for public clients
- Add support for #439
- Client credentials grant updated
- Password grant updated
- Allow support for public clients
- Refresh token grant updated
- Implement Implicit grant
- Bearer token output type
- Remove MAC token output type
- Authorization server rewrite
- Resource server class moved to PSR-7 middleware
- Tests
- Much much better documentation
## [4.1.5] - 2016-01-04
- Enable Symfony 3.0 support (#412)
## [4.1.4] - 2015-11-13
- Fix for determining access token in header (Issue #328)
- Refresh tokens are now returned for MAC responses (Issue #356)
- Added integration list to readme (Issue #341)
- Expose parameter passed to exceptions (Issue #345)
- Removed duplicate routing setup code (Issue #346)
- Docs fix (Issues #347, #360, #380)
- Examples fix (Issues #348, #358)
- Fix typo in docblock (Issue #352)
- Improved timeouts for MAC tokens (Issue #364)
- `hash_hmac()` should output raw binary data, not hexits (Issue #370)
- Improved regex for matching all Base64 characters (Issue #371)
- Fix incorrect signature parameter (Issue #372)
- AuthCodeGrant and RefreshTokenGrant don't require client_secret (Issue #377)
- Added priority argument to event listener (Issue #388)
## [4.1.3] - 2015-03-22
- Docblock, namespace and inconsistency fixes (Issue #303)
- Docblock type fix (Issue #310)
- Example bug fix (Issue #300)
- Updated league/event to ~2.1 (Issue #311)
- Fixed missing session scope (Issue #319)
- Updated interface docs (Issue #323)
- `.travis.yml` updates
## [4.1.2] - 2015-01-01
- Remove side-effects in hash_equals() implementation (Issue #290)
## [4.1.1] - 2014-12-31
- Changed `symfony/http-foundation` dependency version to `~2.4` so package can be installed in Laravel `4.1.*`
## [4.1.0] - 2014-12-27
- Added MAC token support (Issue #158)
- Fixed example init code (Issue #280)
- Toggle refresh token rotation (Issue #286)
- Docblock fixes
## [4.0.5] - 2014-12-15
- Prevent duplicate session in auth code grant (Issue #282)
## [4.0.4] - 2014-12-03
- Ensure refresh token hasn't expired (Issue #270)
## [4.0.3] - 2014-12-02
- Fix bad type hintings (Issue #267)
- Do not forget to set the expire time (Issue #268)
## [4.0.2] - 2014-11-21
- Improved interfaces (Issue #255)
- Learnt how to spell delimiter and so `getScopeDelimiter()` and `setScopeDelimiter()` methods have been renamed
- Docblock improvements (Issue #254)
## [4.0.1] - 2014-11-09
- Alias the master branch in composer.json (Issue #243)
- Numerous PHP CodeSniffer fixes (Issue #244)
- .travis.yml update (Issue #245)
- The getAccessToken method should return an AccessTokenEntity object instead of a string in ResourceServer.php (#246)
## [4.0.0] - 2014-11-08
- Complete rewrite
- Check out the documentation - [http://oauth2.thephpleague.com](http://oauth2.thephpleague.com)
## [3.2.0] - 2014-04-16
- Added the ability to change the algorithm that is used to generate the token strings (Issue #151)
## [3.1.2] - 2014-02-26
- Support Authorization being an environment variable. [See more](http://fortrabbit.com/docs/essentials/quirks-and-constraints#authorization-header)
## [3.1.1] - 2013-12-05
- Normalize headers when `getallheaders()` is available (Issues #108 and #114)
## [3.1.0] - 2013-12-05
- No longer necessary to inject the authorisation server into a grant, the server will inject itself
- Added test for 1419ba8cdcf18dd034c8db9f7de86a2594b68605
## [3.0.1] - 2013-12-02
- Forgot to tell TravisCI from testing PHP 5.3
## [3.0.0] - 2013-12-02
- Fixed spelling of Implicit grant class (Issue #84)
- Travis CI now tests for PHP 5.5
- Fixes for checking headers for resource server (Issues #79 and #)
- The word "bearer" now has a capital "B" in JSON output to match OAuth 2.0 spec
- All grants no longer remove old sessions by default
- All grants now support custom access token TTL (Issue #92)
- All methods which didn't before return a value now return `$this` to support method chaining
- Removed the build in DB providers - these will be put in their own repos to remove baggage in the main repository
- Removed support for PHP 5.3 because this library now uses traits and will use other modern PHP features going forward
- Moved some grant related functions into a trait to reduce duplicate code
## [2.1.1] - 2013-06-02
- Added conditional `isValid()` flag to check for Authorization header only (thanks @alexmcroberts)
- Fixed semantic meaning of `requireScopeParam()` and `requireStateParam()` by changing their default value to true
- Updated some duff docblocks
- Corrected array key call in Resource.php (Issue #63)
## [2.1.0] - 2013-05-10
- Moved zetacomponents/database to "suggest" in composer.json. If you rely on this feature you now need to include " zetacomponents/database" into "require" key in your own composer.json. (Issue #51)
- New method in Refresh grant called `rotateRefreshTokens()`. Pass in `true` to issue a new refresh token each time an access token is refreshed. This parameter needs to be set to true in order to request reduced scopes with the new access token. (Issue #47)
- Rename `key` column in oauth_scopes table to `scope` as `key` is a reserved SQL word. (Issue #45)
- The `scope` parameter is no longer required by default as per the RFC. (Issue #43)
- You can now set multiple default scopes by passing an array into `setDefaultScope()`. (Issue #42)
- The password and client credentials grants now allow for multiple sessions per user. (Issue #32)
- Scopes associated to authorization codes are not held in their own table (Issue #44)
- Database schema updates.
## [2.0.5] - 2013-05-09
- Fixed `oauth_session_token_scopes` table primary key
- Removed `DEFAULT ''` that has slipped into some tables
- Fixed docblock for `SessionInterface::associateRefreshToken()`
## [2.0.4] - 2013-05-09
- Renamed primary key in oauth_client_endpoints table
- Adding missing column to oauth_session_authcodes
### Security
- A refresh token should be bound to a client ID
## [2.0.3] - 2013-05-08
- Fixed a link to code in composer.json
## [2.0.2] - 2013-05-08
- Updated README with wiki guides
- Removed `null` as default parameters in some methods in the storage interfaces
- Fixed license copyright
## [2.0.0] - 2013-05-08
**If you're upgrading from v1.0.8 there are lots of breaking changes**
* Rewrote the session storage interface from scratch so methods are more obvious
* Included a PDO driver which implements the storage interfaces so the library is more "get up and go"
* Further normalised the database structure so all sessions no longer contain infomation related to authorization grant (which may or may not be enabled)
* A session can have multiple associated access tokens
* Induvidual grants can have custom expire times for access tokens
* Authorization codes now have a TTL of 10 minutes by default (can be manually set)
* Refresh tokens now have a TTL of one week by default (can be manually set)
* The client credentials grant will no longer gives out refresh tokens as per the specification
- Rewrote the session storage interface from scratch so methods are more obvious
- Included a PDO driver which implements the storage interfaces so the library is more "get up and go"
- Further normalised the database structure so all sessions no longer contain infomation related to authorization grant (which may or may not be enabled)
- A session can have multiple associated access tokens
- Individual grants can have custom expire times for access tokens
- Authorization codes now have a TTL of 10 minutes by default (can be manually set)
- Refresh tokens now have a TTL of one week by default (can be manually set)
- The client credentials grant will no longer gives out refresh tokens as per the specification
## 1.0.8 (released 2013-03-18)
## [1.0.8] - 2013-03-18
* Fixed check for required state parameter
* Fixed check that user's credentials are correct in Password grant
- Fixed check for required state parameter
- Fixed check that user's credentials are correct in Password grant
## 1.0.7 (released 2013-03-04)
## [1.0.7] - 2013-03-04
* Added method `requireStateParam()`
* Added method `requireScopeParam()`
- Added method `requireStateParam()`
- Added method `requireScopeParam()`
## 1.0.6 (released 2013-02-22)
## [1.0.6] - 2013-02-22
* Added links to tutorials in the README
* Added missing `state` parameter request to the `checkAuthoriseParams()` method.
- Added links to tutorials in the README
- Added missing `state` parameter request to the `checkAuthoriseParams()` method.
## 1.0.5 (released 2013-02-21)
## [1.0.5] - 2013-02-21
* Fixed the SQL example for SessionInterface::getScopes()
- Fixed the SQL example for SessionInterface::getScopes()
## 1.0.3 (released 2013-02-20)
## [1.0.3] - 2013-02-20
* Changed all instances of the "authentication server" to "authorization server"
- Changed all instances of the "authentication server" to "authorization server"
## 1.0.2 (released 2013-02-20)
## [1.0.2] - 2013-02-20
* Fixed MySQL create table order
* Fixed version number in composer.json
- Fixed MySQL create table order
- Fixed version number in composer.json
## 1.0.1 (released 2013-02-19)
## [1.0.1] - 2013-02-19
* Updated AuthServer.php to use `self::getParam()`
- Updated AuthServer.php to use `self::getParam()`
## 1.0.0 (released 2013-02-15)
## 1.0.0 - 2013-02-15
* First major release
- First major release
[Unreleased]: https://github.com/thephpleague/oauth2-server/compare/8.0.0...HEAD
[8.0.0]: https://github.com/thephpleague/oauth2-server/compare/7.4.0...8.0.0
[7.4.0]: https://github.com/thephpleague/oauth2-server/compare/7.3.3...7.4.0
[7.3.3]: https://github.com/thephpleague/oauth2-server/compare/7.3.2...7.3.3
[7.3.2]: https://github.com/thephpleague/oauth2-server/compare/7.3.1...7.3.2
[7.3.1]: https://github.com/thephpleague/oauth2-server/compare/7.3.0...7.3.1
[7.3.0]: https://github.com/thephpleague/oauth2-server/compare/7.2.0...7.3.0
[7.2.0]: https://github.com/thephpleague/oauth2-server/compare/7.1.1...7.2.0
[7.1.1]: https://github.com/thephpleague/oauth2-server/compare/7.1.0...7.1.1
[7.1.0]: https://github.com/thephpleague/oauth2-server/compare/7.0.0...7.1.0
[7.0.0]: https://github.com/thephpleague/oauth2-server/compare/6.1.1...7.0.0
[6.1.1]: https://github.com/thephpleague/oauth2-server/compare/6.0.0...6.1.1
[6.1.0]: https://github.com/thephpleague/oauth2-server/compare/6.0.2...6.1.0
[6.0.2]: https://github.com/thephpleague/oauth2-server/compare/6.0.1...6.0.2
[6.0.1]: https://github.com/thephpleague/oauth2-server/compare/6.0.0...6.0.1
[6.0.0]: https://github.com/thephpleague/oauth2-server/compare/5.1.4...6.0.0
[5.1.4]: https://github.com/thephpleague/oauth2-server/compare/5.1.3...5.1.4
[5.1.3]: https://github.com/thephpleague/oauth2-server/compare/5.1.2...5.1.3
[5.1.2]: https://github.com/thephpleague/oauth2-server/compare/5.1.1...5.1.2
[5.1.1]: https://github.com/thephpleague/oauth2-server/compare/5.1.0...5.1.1
[5.1.0]: https://github.com/thephpleague/oauth2-server/compare/5.0.2...5.1.0
[5.0.3]: https://github.com/thephpleague/oauth2-server/compare/5.0.3...5.0.2
[5.0.2]: https://github.com/thephpleague/oauth2-server/compare/5.0.1...5.0.2
[5.0.1]: https://github.com/thephpleague/oauth2-server/compare/5.0.0...5.0.1
[5.0.0]: https://github.com/thephpleague/oauth2-server/compare/5.0.0-RC2...5.0.0
[5.0.0-RC2]: https://github.com/thephpleague/oauth2-server/compare/5.0.0-RC1...5.0.0-RC2
[5.0.0-RC1]: https://github.com/thephpleague/oauth2-server/compare/4.1.5...5.0.0-RC1
[4.1.7]: https://github.com/thephpleague/oauth2-server/compare/4.1.6...4.1.7
[4.1.6]: https://github.com/thephpleague/oauth2-server/compare/4.1.5...4.1.6
[4.1.5]: https://github.com/thephpleague/oauth2-server/compare/4.1.4...4.1.5
[4.1.4]: https://github.com/thephpleague/oauth2-server/compare/4.1.3...4.1.4
[4.1.3]: https://github.com/thephpleague/oauth2-server/compare/4.1.2...4.1.3
[4.1.2]: https://github.com/thephpleague/oauth2-server/compare/4.1.1...4.1.2
[4.1.1]: https://github.com/thephpleague/oauth2-server/compare/4.0.0...4.1.1
[4.1.0]: https://github.com/thephpleague/oauth2-server/compare/4.0.5...4.1.0
[4.0.5]: https://github.com/thephpleague/oauth2-server/compare/4.0.4...4.0.5
[4.0.4]: https://github.com/thephpleague/oauth2-server/compare/4.0.3...4.0.4
[4.0.3]: https://github.com/thephpleague/oauth2-server/compare/4.0.2...4.0.3
[4.0.2]: https://github.com/thephpleague/oauth2-server/compare/4.0.1...4.0.2
[4.0.1]: https://github.com/thephpleague/oauth2-server/compare/4.0.0...4.0.1
[4.0.0]: https://github.com/thephpleague/oauth2-server/compare/3.2.0...4.0.0
[3.2.0]: https://github.com/thephpleague/oauth2-server/compare/3.1.2...3.2.0
[3.1.2]: https://github.com/thephpleague/oauth2-server/compare/3.1.1...3.1.2
[3.1.1]: https://github.com/thephpleague/oauth2-server/compare/3.1.0...3.1.1
[3.1.0]: https://github.com/thephpleague/oauth2-server/compare/3.0.1...3.1.0
[3.0.1]: https://github.com/thephpleague/oauth2-server/compare/3.0.0...3.0.1
[3.0.0]: https://github.com/thephpleague/oauth2-server/compare/2.1.1...3.0.0
[2.1.1]: https://github.com/thephpleague/oauth2-server/compare/2.1.0...2.1.1
[2.1.0]: https://github.com/thephpleague/oauth2-server/compare/2.0.5...2.1.0
[2.0.5]: https://github.com/thephpleague/oauth2-server/compare/2.0.4...2.0.5
[2.0.4]: https://github.com/thephpleague/oauth2-server/compare/2.0.3...2.0.4
[2.0.3]: https://github.com/thephpleague/oauth2-server/compare/2.0.2...2.0.3
[2.0.2]: https://github.com/thephpleague/oauth2-server/compare/2.0.0...2.0.2
[2.0.0]: https://github.com/thephpleague/oauth2-server/compare/1.0.8...2.0.0
[1.0.8]: https://github.com/thephpleague/oauth2-server/compare/1.0.7...1.0.8
[1.0.7]: https://github.com/thephpleague/oauth2-server/compare/1.0.6...1.0.7
[1.0.6]: https://github.com/thephpleague/oauth2-server/compare/1.0.5...1.0.6
[1.0.5]: https://github.com/thephpleague/oauth2-server/compare/1.0.3...1.0.5
[1.0.3]: https://github.com/thephpleague/oauth2-server/compare/1.0.2...1.0.3
[1.0.2]: https://github.com/thephpleague/oauth2-server/compare/1.0.1...1.0.2
[1.0.1]: https://github.com/thephpleague/oauth2-server/compare/1.0.0...1.0.1

73
CODE_OF_CONDUCT.md Normal file
View File

@@ -0,0 +1,73 @@
# Contributor Covenant Code of Conduct
## Our Pledge
In the interest of fostering an open and welcoming environment, we as
contributors and maintainers pledge to making participation in our project and
our community a harassment-free experience for everyone, regardless of age, body
size, disability, ethnicity, gender identity and expression, level of experience,
education, socio-economic status, nationality, personal appearance, race,
religion, or sexual identity and orientation.
## Our Standards
Examples of behavior that contributes to creating a positive environment
include:
* Using welcoming and inclusive language
* Being respectful of differing viewpoints and experiences
* Gracefully accepting constructive criticism
* Focusing on what is best for the community
* Showing empathy towards other community members
Examples of unacceptable behavior by participants include:
* The use of sexualized language or imagery and unwelcome sexual attention or
advances
* Trolling, insulting/derogatory comments, and personal or political attacks
* Public or private harassment
* Publishing others' private information, such as a physical or electronic
address, without explicit permission
* Other conduct which could reasonably be considered inappropriate in a
professional setting
## Our Responsibilities
Project maintainers are responsible for clarifying the standards of acceptable
behavior and are expected to take appropriate and fair corrective action in
response to any instances of unacceptable behavior.
Project maintainers have the right and responsibility to remove, edit, or
reject comments, commits, code, wiki edits, issues, and other contributions
that are not aligned to this Code of Conduct, or to ban temporarily or
permanently any contributor for other behaviors that they deem inappropriate,
threatening, offensive, or harmful.
## Scope
This Code of Conduct applies both within project spaces and in public spaces
when an individual is representing the project or its community. Examples of
representing a project or community include using an official project e-mail
address, posting via an official social media account, or acting as an appointed
representative at an online or offline event. Representation of a project may be
further defined and clarified by project maintainers.
## Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior may be
reported by contacting the project team at andrew@noexceptions.io. All
complaints will be reviewed and investigated and will result in a response that
is deemed necessary and appropriate to the circumstances. The project team is
obligated to maintain confidentiality with regard to the reporter of an incident.
Further details of specific enforcement policies may be posted separately.
Project maintainers who do not follow or enforce the Code of Conduct in good
faith may face temporary or permanent repercussions as determined by other
members of the project's leadership.
## Attribution
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html
[homepage]: https://www.contributor-covenant.org

View File

@@ -1,7 +1,7 @@
Thanks for contributing to this project.
**Please submit your pull request against the `develop` branch only.**
**Please submit your pull request against the `master` branch only.**
Please ensure that you run `phpunit` from the project root after you've made any changes.

View File

@@ -1,68 +1,93 @@
# 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)
[![Build Status](https://img.shields.io/travis/thephpleague/oauth2-server/master.svg?style=flat-square)](https://travis-ci.org/thephpleague/oauth2-server)
[![Coverage Status](https://img.shields.io/scrutinizer/coverage/g/thephpleague/oauth2-server.svg?style=flat-square)](https://scrutinizer-ci.com/g/thephpleague/oauth2-server/code-structure)
[![Quality Score](https://img.shields.io/scrutinizer/g/thephpleague/oauth2-server.svg?style=flat-square)](https://scrutinizer-ci.com/g/thephpleague/oauth2-server)
[![Total Downloads](https://img.shields.io/packagist/dt/league/oauth2-server.svg?style=flat-square)](https://packagist.org/packages/league/oauth2-server) [![Gitter](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/thephpleague/oauth2-server?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge)
[![Total Downloads](https://img.shields.io/packagist/dt/league/oauth2-server.svg?style=flat-square)](https://packagist.org/packages/league/oauth2-server)
[![PHPStan](https://img.shields.io/badge/PHPStan-enabled-brightgreen.svg?style=flat-square)](https://github.com/phpstan/phpstan)
`league/oauth2-server` is a standards compliant implementation of an [OAuth 2.0](https://tools.ietf.org/html/rfc6749) authorization server written in PHP which makes working with OAuth 2.0 trivial. You can easily configure an OAuth 2.0 server to protect your API with access tokens, or allow clients to request new access tokens and refresh them.
A standards compliant [OAuth 2.0](http://tools.ietf.org/wg/oauth/draft-ietf-oauth-v2/) authorization server and resource server written in PHP which makes working with OAuth 2.0 trivial. You can easily configure an OAuth 2.0 server to protect your API with access tokens, or allow clients to request new access tokens and refresh them.
It supports out of the box the following grants:
Out of the box it supports the following grants:
* Authorization code grant
* Implicit grant
* Client credentials grant
* Resource owner password credentials grant
* Refresh grant
You can also define your own grants.
The following RFCs are implemented:
In addition it supports the following token types:
* Bearer tokens
* MAC tokens
* JSON web tokens (coming soon)
You can also create you own tokens.
* [RFC6749 "OAuth 2.0"](https://tools.ietf.org/html/rfc6749)
* [RFC6750 " The OAuth 2.0 Authorization Framework: Bearer Token Usage"](https://tools.ietf.org/html/rfc6750)
* [RFC7519 "JSON Web Token (JWT)"](https://tools.ietf.org/html/rfc7519)
* [RFC7636 "Proof Key for Code Exchange by OAuth Public Clients"](https://tools.ietf.org/html/rfc7636)
This library was created by Alex Bilbie. Find him on Twitter at [@alexbilbie](https://twitter.com/alexbilbie).
## Requirements
The following versions of PHP are supported:
* PHP 5.4
* PHP 5.5
* PHP 5.6
* HHVM
* PHP 7.1
* PHP 7.2
* PHP 7.3
The `openssl` and `json` extensions are also required.
All HTTP messages passed to the server should be [PSR-7 compliant](https://www.php-fig.org/psr/psr-7/). This ensures interoperability with other packages and frameworks.
## Installation
```
composer require league/oauth2-server
```
## Documentation
This library has [full documentation](http://oauth2.thephpleague.com), powered by [Jekyll](http://jekyllrb.com/).
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/).
Contribute to this documentation in the [gh-pages branch](https://github.com/thephpleague/oauth2-server/tree/gh-pages/).
## Testing
The library uses [PHPUnit](https://phpunit.de/) for unit tests and [PHPStan](https://github.com/phpstan/phpstan) for static analysis of the code.
```
vendor/bin/phpunit
vendor/bin/phpstan analyse -l 7 -c phpstan.neon src tests
```
## Continous Integration
We use [Travis CI](https://travis-ci.org/), [Scrutinizer](https://scrutinizer-ci.com/), and [StyleCI](https://styleci.io/) for continuous integration. Check out [our](https://github.com/thephpleague/oauth2-server/blob/master/.travis.yml) [configuration](https://github.com/thephpleague/oauth2-server/blob/master/.scrutinizer.yml) [files](https://github.com/thephpleague/oauth2-server/blob/master/.styleci.yml) if you'd like to know more.
## Community Integrations
* [Drupal](https://www.drupal.org/project/simple_oauth)
* [Laravel Passport](https://github.com/laravel/passport)
* [OAuth 2 Server for CakePHP 3](https://github.com/uafrica/oauth-server)
* [OAuth 2 Server for Expressive](https://github.com/zendframework/zend-expressive-authentication-oauth2)
* [Trikoder OAuth 2 Bundle (Symfony)](https://github.com/trikoder/oauth2-bundle)
## Changelog
[See the project releases page](https://github.com/thephpleague/oauth2-server/releases)
See the [project changelog](https://github.com/thephpleague/oauth2-server/blob/master/CHANGELOG.md)
## Contributing
Please see [CONTRIBUTING](https://github.com/thephpleague/oauth2-server/blob/master/CONTRIBUTING.md) for details.
## Integration
- [CakePHP 3](https://github.com/uafrica/oauth-server)
- [Laravel](https://github.com/lucadegasperi/oauth2-server-laravel)
Contributions are always welcome. Please see [CONTRIBUTING.md](https://github.com/thephpleague/oauth2-server/blob/master/CONTRIBUTING.md) and [CODE_OF_CONDUCT.md](https://github.com/thephpleague/oauth2-server/blob/master/CODE_OF_CONDUCT.md) for details.
## Support
Bugs and feature request are tracked on [GitHub](https://github.com/thephpleague/oauth2-server/issues)
Bugs and feature request are tracked on [GitHub](https://github.com/thephpleague/oauth2-server/issues).
If you have any questions about OAuth _please_ open a ticket here; please **don't** email the address below.
## Security
If you discover any security related issues, please email hello@alexbilbie.com instead of using the issue tracker.
If you discover any security related issues, please email `andrew@noexceptions.io` instead of using the issue tracker.
## License
@@ -70,14 +95,14 @@ This package is released under the MIT License. See the bundled [LICENSE](https:
## Credits
This code is principally developed and maintained by [Alex Bilbie](https://twitter.com/alexbilbie).
This code is principally developed and maintained by [Andy Millington](https://twitter.com/Sephster).
Special thanks to:
Between 2012 and 2017 this library was developed and maintained by [Alex Bilbie](https://alexbilbie.com/).
* [Dan Horrigan](https://github.com/dandoescode)
* [Nick Jackson](https://github.com/jacksonj04)
* [Michael Gooden](https://github.com/MichaelGooden)
* [Phil Sturgeon](https://github.com/philsturgeon)
* [and all the other contributors](https://github.com/thephpleague/oauth2-server/contributors)
PHP OAuth 2.0 Server is one of many packages provided by The PHP League. To find out more, please visit [our website](https://thephpleague.com).
Special thanks to [all of these awesome contributors](https://github.com/thephpleague/oauth2-server/contributors).
Additional thanks go to the [Mozilla Secure Open Source Fund](https://wiki.mozilla.org/MOSS/Secure_Open_Source) for funding a security audit of this library.
The initial code was developed as part of the [Linkey](http://linkey.blogs.lincoln.ac.uk) project which was funded by [JISC](http://jisc.ac.uk) under the Access and Identity Management programme.

View File

@@ -1,59 +1,72 @@
{
"name": "league/oauth2-server",
"description": "A lightweight and powerful OAuth 2.0 authorization and resource server library with support for all the core specification grants. This library will allow you to secure your API with OAuth and allow your applications users to approve apps that want to access their data from your API.",
"homepage": "http://oauth2.thephpleague.com/",
"license": "MIT",
"require": {
"php": ">=5.4.0",
"symfony/http-foundation": "~2.4|~3.0",
"league/event": "~2.1"
},
"require-dev": {
"phpunit/phpunit": "4.3.*",
"mockery/mockery": "0.9.*"
},
"repositories": [
{
"type": "git",
"url": "https://github.com/thephpleague/oauth2-server.git"
}
],
"keywords": [
"oauth",
"oauth2",
"oauth 2",
"oauth 2.0",
"server",
"auth",
"authorization",
"authorisation",
"authentication",
"resource",
"api",
"auth",
"protect",
"secure"
],
"authors": [
{
"name": "Alex Bilbie",
"email": "hello@alexbilbie.com",
"homepage": "http://www.alexbilbie.com",
"role": "Developer"
}
],
"replace": {
"lncd/oauth2": "*",
"league/oauth2server": "*"
},
"autoload": {
"psr-4": {
"League\\OAuth2\\Server\\": "src/"
}
},
"autoload-dev": {
"psr-4": {
"LeagueTests\\": "tests/unit/"
}
}
"name": "league/oauth2-server",
"description": "A lightweight and powerful OAuth 2.0 authorization and resource server library with support for all the core specification grants. This library will allow you to secure your API with OAuth and allow your applications users to approve apps that want to access their data from your API.",
"homepage": "https://oauth2.thephpleague.com/",
"license": "MIT",
"require": {
"php": ">=7.1.0",
"ext-openssl": "*",
"league/event": "^2.2",
"lcobucci/jwt": "^3.3.1",
"psr/http-message": "^1.0.1",
"defuse/php-encryption": "^2.2.1",
"ext-json": "*"
},
"require-dev": {
"phpunit/phpunit": "^7.5.13 || ^8.2.3",
"zendframework/zend-diactoros": "^2.1.2",
"phpstan/phpstan": "^0.11.8",
"phpstan/phpstan-phpunit": "^0.11.2",
"roave/security-advisories": "dev-master"
},
"repositories": [
{
"type": "git",
"url": "https://github.com/thephpleague/oauth2-server.git"
}
],
"keywords": [
"oauth",
"oauth2",
"oauth 2",
"oauth 2.0",
"server",
"auth",
"authorization",
"authorisation",
"authentication",
"resource",
"api",
"auth",
"protect",
"secure"
],
"authors": [
{
"name": "Alex Bilbie",
"email": "hello@alexbilbie.com",
"homepage": "http://www.alexbilbie.com",
"role": "Developer"
},
{
"name": "Andy Millington",
"email": "andrew@noexceptions.io",
"homepage": "https://www.noexceptions.io",
"role": "Developer"
}
],
"replace": {
"lncd/oauth2": "*",
"league/oauth2server": "*"
},
"autoload": {
"psr-4": {
"League\\OAuth2\\Server\\": "src/"
}
},
"autoload-dev": {
"psr-4": {
"LeagueTests\\": "tests/"
}
}
}

53
examples/README.md Normal file
View File

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

18
examples/composer.json Normal file
View File

@@ -0,0 +1,18 @@
{
"require": {
"slim/slim": "^3.0.0"
},
"require-dev": {
"league/event": "^2.2",
"lcobucci/jwt": "^3.3",
"psr/http-message": "^1.0",
"defuse/php-encryption": "^2.2",
"zendframework/zend-diactoros": "^2.1.0"
},
"autoload": {
"psr-4": {
"OAuth2ServerExamples\\": "src/",
"League\\OAuth2\\Server\\": "../src/"
}
}
}

647
examples/composer.lock generated Normal file
View File

@@ -0,0 +1,647 @@
{
"_readme": [
"This file locks the dependencies of your project to a known state",
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "a7f5c3fdcadb17399bbd97f15e1b11f1",
"packages": [
{
"name": "container-interop/container-interop",
"version": "1.2.0",
"source": {
"type": "git",
"url": "https://github.com/container-interop/container-interop.git",
"reference": "79cbf1341c22ec75643d841642dd5d6acd83bdb8"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/container-interop/container-interop/zipball/79cbf1341c22ec75643d841642dd5d6acd83bdb8",
"reference": "79cbf1341c22ec75643d841642dd5d6acd83bdb8",
"shasum": ""
},
"require": {
"psr/container": "^1.0"
},
"type": "library",
"autoload": {
"psr-4": {
"Interop\\Container\\": "src/Interop/Container/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"description": "Promoting the interoperability of container objects (DIC, SL, etc.)",
"homepage": "https://github.com/container-interop/container-interop",
"time": "2017-02-14T19:40:03+00:00"
},
{
"name": "nikic/fast-route",
"version": "v1.3.0",
"source": {
"type": "git",
"url": "https://github.com/nikic/FastRoute.git",
"reference": "181d480e08d9476e61381e04a71b34dc0432e812"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/nikic/FastRoute/zipball/181d480e08d9476e61381e04a71b34dc0432e812",
"reference": "181d480e08d9476e61381e04a71b34dc0432e812",
"shasum": ""
},
"require": {
"php": ">=5.4.0"
},
"require-dev": {
"phpunit/phpunit": "^4.8.35|~5.7"
},
"type": "library",
"autoload": {
"psr-4": {
"FastRoute\\": "src/"
},
"files": [
"src/functions.php"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Nikita Popov",
"email": "nikic@php.net"
}
],
"description": "Fast request router for PHP",
"keywords": [
"router",
"routing"
],
"time": "2018-02-13T20:26:39+00:00"
},
{
"name": "pimple/pimple",
"version": "v3.2.3",
"source": {
"type": "git",
"url": "https://github.com/silexphp/Pimple.git",
"reference": "9e403941ef9d65d20cba7d54e29fe906db42cf32"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/silexphp/Pimple/zipball/9e403941ef9d65d20cba7d54e29fe906db42cf32",
"reference": "9e403941ef9d65d20cba7d54e29fe906db42cf32",
"shasum": ""
},
"require": {
"php": ">=5.3.0",
"psr/container": "^1.0"
},
"require-dev": {
"symfony/phpunit-bridge": "^3.2"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "3.2.x-dev"
}
},
"autoload": {
"psr-0": {
"Pimple": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Fabien Potencier",
"email": "fabien@symfony.com"
}
],
"description": "Pimple, a simple Dependency Injection Container",
"homepage": "http://pimple.sensiolabs.org",
"keywords": [
"container",
"dependency injection"
],
"time": "2018-01-21T07:42:36+00:00"
},
{
"name": "psr/container",
"version": "1.0.0",
"source": {
"type": "git",
"url": "https://github.com/php-fig/container.git",
"reference": "b7ce3b176482dbbc1245ebf52b181af44c2cf55f"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/php-fig/container/zipball/b7ce3b176482dbbc1245ebf52b181af44c2cf55f",
"reference": "b7ce3b176482dbbc1245ebf52b181af44c2cf55f",
"shasum": ""
},
"require": {
"php": ">=5.3.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.0.x-dev"
}
},
"autoload": {
"psr-4": {
"Psr\\Container\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "PHP-FIG",
"homepage": "http://www.php-fig.org/"
}
],
"description": "Common Container Interface (PHP FIG PSR-11)",
"homepage": "https://github.com/php-fig/container",
"keywords": [
"PSR-11",
"container",
"container-interface",
"container-interop",
"psr"
],
"time": "2017-02-14T16:28:37+00:00"
},
{
"name": "psr/http-message",
"version": "1.0.1",
"source": {
"type": "git",
"url": "https://github.com/php-fig/http-message.git",
"reference": "f6561bf28d520154e4b0ec72be95418abe6d9363"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/php-fig/http-message/zipball/f6561bf28d520154e4b0ec72be95418abe6d9363",
"reference": "f6561bf28d520154e4b0ec72be95418abe6d9363",
"shasum": ""
},
"require": {
"php": ">=5.3.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.0.x-dev"
}
},
"autoload": {
"psr-4": {
"Psr\\Http\\Message\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "PHP-FIG",
"homepage": "http://www.php-fig.org/"
}
],
"description": "Common interface for HTTP messages",
"homepage": "https://github.com/php-fig/http-message",
"keywords": [
"http",
"http-message",
"psr",
"psr-7",
"request",
"response"
],
"time": "2016-08-06T14:39:51+00:00"
},
{
"name": "slim/slim",
"version": "3.12.1",
"source": {
"type": "git",
"url": "https://github.com/slimphp/Slim.git",
"reference": "eaee12ef8d0750db62b8c548016d82fb33addb6b"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/slimphp/Slim/zipball/eaee12ef8d0750db62b8c548016d82fb33addb6b",
"reference": "eaee12ef8d0750db62b8c548016d82fb33addb6b",
"shasum": ""
},
"require": {
"container-interop/container-interop": "^1.2",
"nikic/fast-route": "^1.0",
"php": ">=5.5.0",
"pimple/pimple": "^3.0",
"psr/container": "^1.0",
"psr/http-message": "^1.0"
},
"provide": {
"psr/http-message-implementation": "1.0"
},
"require-dev": {
"phpunit/phpunit": "^4.0",
"squizlabs/php_codesniffer": "^2.5"
},
"type": "library",
"autoload": {
"psr-4": {
"Slim\\": "Slim"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Rob Allen",
"email": "rob@akrabat.com",
"homepage": "http://akrabat.com"
},
{
"name": "Josh Lockhart",
"email": "hello@joshlockhart.com",
"homepage": "https://joshlockhart.com"
},
{
"name": "Gabriel Manricks",
"email": "gmanricks@me.com",
"homepage": "http://gabrielmanricks.com"
},
{
"name": "Andrew Smith",
"email": "a.smith@silentworks.co.uk",
"homepage": "http://silentworks.co.uk"
}
],
"description": "Slim is a PHP micro framework that helps you quickly write simple yet powerful web applications and APIs",
"homepage": "https://slimframework.com",
"keywords": [
"api",
"framework",
"micro",
"router"
],
"time": "2019-04-16T16:47:29+00:00"
}
],
"packages-dev": [
{
"name": "defuse/php-encryption",
"version": "v2.2.1",
"source": {
"type": "git",
"url": "https://github.com/defuse/php-encryption.git",
"reference": "0f407c43b953d571421e0020ba92082ed5fb7620"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/defuse/php-encryption/zipball/0f407c43b953d571421e0020ba92082ed5fb7620",
"reference": "0f407c43b953d571421e0020ba92082ed5fb7620",
"shasum": ""
},
"require": {
"ext-openssl": "*",
"paragonie/random_compat": ">= 2",
"php": ">=5.4.0"
},
"require-dev": {
"nikic/php-parser": "^2.0|^3.0|^4.0",
"phpunit/phpunit": "^4|^5"
},
"bin": [
"bin/generate-defuse-key"
],
"type": "library",
"autoload": {
"psr-4": {
"Defuse\\Crypto\\": "src"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Taylor Hornby",
"email": "taylor@defuse.ca",
"homepage": "https://defuse.ca/"
},
{
"name": "Scott Arciszewski",
"email": "info@paragonie.com",
"homepage": "https://paragonie.com"
}
],
"description": "Secure PHP Encryption Library",
"keywords": [
"aes",
"authenticated encryption",
"cipher",
"crypto",
"cryptography",
"encrypt",
"encryption",
"openssl",
"security",
"symmetric key cryptography"
],
"time": "2018-07-24T23:27:56+00:00"
},
{
"name": "lcobucci/jwt",
"version": "3.3.1",
"source": {
"type": "git",
"url": "https://github.com/lcobucci/jwt.git",
"reference": "a11ec5f4b4d75d1fcd04e133dede4c317aac9e18"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/lcobucci/jwt/zipball/a11ec5f4b4d75d1fcd04e133dede4c317aac9e18",
"reference": "a11ec5f4b4d75d1fcd04e133dede4c317aac9e18",
"shasum": ""
},
"require": {
"ext-mbstring": "*",
"ext-openssl": "*",
"php": "^5.6 || ^7.0"
},
"require-dev": {
"mikey179/vfsstream": "~1.5",
"phpmd/phpmd": "~2.2",
"phpunit/php-invoker": "~1.1",
"phpunit/phpunit": "^5.7 || ^7.3",
"squizlabs/php_codesniffer": "~2.3"
},
"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": "2019-05-24T18:30:49+00:00"
},
{
"name": "league/event",
"version": "2.2.0",
"source": {
"type": "git",
"url": "https://github.com/thephpleague/event.git",
"reference": "d2cc124cf9a3fab2bb4ff963307f60361ce4d119"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/thephpleague/event/zipball/d2cc124cf9a3fab2bb4ff963307f60361ce4d119",
"reference": "d2cc124cf9a3fab2bb4ff963307f60361ce4d119",
"shasum": ""
},
"require": {
"php": ">=5.4.0"
},
"require-dev": {
"henrikbjorn/phpspec-code-coverage": "~1.0.1",
"phpspec/phpspec": "^2.2"
},
"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": "2018-11-26T11:52:41+00:00"
},
{
"name": "paragonie/random_compat",
"version": "v9.99.99",
"source": {
"type": "git",
"url": "https://github.com/paragonie/random_compat.git",
"reference": "84b4dfb120c6f9b4ff7b3685f9b8f1aa365a0c95"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/paragonie/random_compat/zipball/84b4dfb120c6f9b4ff7b3685f9b8f1aa365a0c95",
"reference": "84b4dfb120c6f9b4ff7b3685f9b8f1aa365a0c95",
"shasum": ""
},
"require": {
"php": "^7"
},
"require-dev": {
"phpunit/phpunit": "4.*|5.*",
"vimeo/psalm": "^1"
},
"suggest": {
"ext-libsodium": "Provides a modern crypto API that can be used to generate random bytes."
},
"type": "library",
"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",
"polyfill",
"pseudorandom",
"random"
],
"time": "2018-07-02T15:55:56+00:00"
},
{
"name": "psr/http-factory",
"version": "1.0.1",
"source": {
"type": "git",
"url": "https://github.com/php-fig/http-factory.git",
"reference": "12ac7fcd07e5b077433f5f2bee95b3a771bf61be"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/php-fig/http-factory/zipball/12ac7fcd07e5b077433f5f2bee95b3a771bf61be",
"reference": "12ac7fcd07e5b077433f5f2bee95b3a771bf61be",
"shasum": ""
},
"require": {
"php": ">=7.0.0",
"psr/http-message": "^1.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.0.x-dev"
}
},
"autoload": {
"psr-4": {
"Psr\\Http\\Message\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "PHP-FIG",
"homepage": "http://www.php-fig.org/"
}
],
"description": "Common interfaces for PSR-7 HTTP message factories",
"keywords": [
"factory",
"http",
"message",
"psr",
"psr-17",
"psr-7",
"request",
"response"
],
"time": "2019-04-30T12:38:16+00:00"
},
{
"name": "zendframework/zend-diactoros",
"version": "2.1.3",
"source": {
"type": "git",
"url": "https://github.com/zendframework/zend-diactoros.git",
"reference": "279723778c40164bcf984a2df12ff2c6ec5e61c1"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/zendframework/zend-diactoros/zipball/279723778c40164bcf984a2df12ff2c6ec5e61c1",
"reference": "279723778c40164bcf984a2df12ff2c6ec5e61c1",
"shasum": ""
},
"require": {
"php": "^7.1",
"psr/http-factory": "^1.0",
"psr/http-message": "^1.0"
},
"provide": {
"psr/http-factory-implementation": "1.0",
"psr/http-message-implementation": "1.0"
},
"require-dev": {
"ext-dom": "*",
"ext-libxml": "*",
"http-interop/http-factory-tests": "^0.5.0",
"php-http/psr7-integration-tests": "dev-master",
"phpunit/phpunit": "^7.0.2",
"zendframework/zend-coding-standard": "~1.0.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "2.1.x-dev",
"dev-develop": "2.2.x-dev",
"dev-release-1.8": "1.8.x-dev"
}
},
"autoload": {
"files": [
"src/functions/create_uploaded_file.php",
"src/functions/marshal_headers_from_sapi.php",
"src/functions/marshal_method_from_sapi.php",
"src/functions/marshal_protocol_version_from_sapi.php",
"src/functions/marshal_uri_from_sapi.php",
"src/functions/normalize_server.php",
"src/functions/normalize_uploaded_files.php",
"src/functions/parse_cookie_header.php"
],
"psr-4": {
"Zend\\Diactoros\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"description": "PSR HTTP Message implementations",
"keywords": [
"http",
"psr",
"psr-7"
],
"time": "2019-07-10T16:13:25+00:00"
}
],
"aliases": [],
"minimum-stability": "stable",
"stability-flags": [],
"prefer-stable": false,
"prefer-lowest": false,
"platform": [],
"platform-dev": []
}

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

@@ -0,0 +1,74 @@
<?php
use League\OAuth2\Server\ResourceServer;
use OAuth2ServerExamples\Repositories\AccessTokenRepository;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Slim\App;
include __DIR__ . '/../vendor/autoload.php';
$app = new App([
// 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(ResourceServer::class)
)
);
// 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',
],
];
$totalUsers = count($users);
// 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 < $totalUsers; $i++) {
unset($users[$i]['name']);
}
}
// 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 < $totalUsers; $i++) {
unset($users[$i]['email']);
}
}
$response->getBody()->write(json_encode($users));
return $response->withStatus(200);
}
);
$app->run();

View File

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

View File

@@ -0,0 +1,78 @@
<?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 OAuth2ServerExamples\Repositories\AccessTokenRepository;
use OAuth2ServerExamples\Repositories\ClientRepository;
use OAuth2ServerExamples\Repositories\ScopeRepository;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Slim\App;
use Zend\Diactoros\Stream;
include __DIR__ . '/../vendor/autoload.php';
$app = new App([
'settings' => [
'displayErrorDetails' => true,
],
AuthorizationServer::class => function () {
// Init our repositories
$clientRepository = new ClientRepository(); // instance of ClientRepositoryInterface
$scopeRepository = new ScopeRepository(); // instance of ScopeRepositoryInterface
$accessTokenRepository = new AccessTokenRepository(); // instance of AccessTokenRepositoryInterface
// 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
// Setup the authorization server
$server = new AuthorizationServer(
$clientRepository,
$accessTokenRepository,
$scopeRepository,
$privateKey,
'lxZFUEsBCJ2Yb14IF2ygAHI5N4+ZAUXXaSeeJm6+twsUmIen'
);
// Enable the client credentials grant on the server
$server->enableGrantType(
new \League\OAuth2\Server\Grant\ClientCredentialsGrant(),
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\AuthorizationServer $server */
$server = $app->getContainer()->get(AuthorizationServer::class);
try {
// 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());
return $response->withStatus(500)->withBody($body);
}
});
$app->run();

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

View File

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

View File

@@ -0,0 +1,72 @@
<?php
use League\OAuth2\Server\AuthorizationServer;
use League\OAuth2\Server\Exception\OAuthServerException;
use League\OAuth2\Server\Grant\PasswordGrant;
use OAuth2ServerExamples\Repositories\AccessTokenRepository;
use OAuth2ServerExamples\Repositories\ClientRepository;
use OAuth2ServerExamples\Repositories\RefreshTokenRepository;
use OAuth2ServerExamples\Repositories\ScopeRepository;
use OAuth2ServerExamples\Repositories\UserRepository;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Slim\App;
include __DIR__ . '/../vendor/autoload.php';
$app = new App([
// Add the authorization server to the DI container
AuthorizationServer::class => function () {
// Setup the authorization server
$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
'lxZFUEsBCJ2Yb14IF2ygAHI5N4+ZAUXXaSeeJm6+twsUmIen' // encryption 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(
$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\AuthorizationServer $server */
$server = $app->getContainer()->get(AuthorizationServer::class);
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

@@ -0,0 +1,73 @@
<?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 OAuth2ServerExamples\Repositories\AccessTokenRepository;
use OAuth2ServerExamples\Repositories\ClientRepository;
use OAuth2ServerExamples\Repositories\RefreshTokenRepository;
use OAuth2ServerExamples\Repositories\ScopeRepository;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Slim\App;
include __DIR__ . '/../vendor/autoload.php';
$app = new App([
'settings' => [
'displayErrorDetails' => true,
],
AuthorizationServer::class => function () {
// Init our repositories
$clientRepository = new ClientRepository();
$accessTokenRepository = new AccessTokenRepository();
$scopeRepository = new ScopeRepository();
$refreshTokenRepository = new RefreshTokenRepository();
$privateKeyPath = 'file://' . __DIR__ . '/../private.key';
// Setup the authorization server
$server = new AuthorizationServer(
$clientRepository,
$accessTokenRepository,
$scopeRepository,
$privateKeyPath,
'lxZFUEsBCJ2Yb14IF2ygAHI5N4+ZAUXXaSeeJm6+twsUmIen'
);
// 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(
$grant,
new \DateInterval('PT1H') // The new access token will expire after 1 hour
);
return $server;
},
]);
$app->post('/access_token', function (ServerRequestInterface $request, ResponseInterface $response) use ($app) {
/* @var \League\OAuth2\Server\AuthorizationServer $server */
$server = $app->getContainer()->get(AuthorizationServer::class);
try {
return $server->respondToAccessTokenRequest($request, $response);
} catch (OAuthServerException $exception) {
return $exception->generateHttpResponse($response);
} catch (\Exception $exception) {
$response->getBody()->write($exception->getMessage());
return $response->withStatus(500);
}
});
$app->run();

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

@@ -0,0 +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\ClientEntityInterface;
use League\OAuth2\Server\Entities\Traits\ClientTrait;
use League\OAuth2\Server\Entities\Traits\EntityTrait;
class ClientEntity implements ClientEntityInterface
{
use EntityTrait, ClientTrait;
public function setName($name)
{
$this->name = $name;
}
public function setRedirectUri($uri)
{
$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

@@ -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\ScopeEntityInterface;
use League\OAuth2\Server\Entities\Traits\EntityTrait;
use League\OAuth2\Server\Entities\Traits\ScopeTrait;
class ScopeEntity implements ScopeEntityInterface
{
use EntityTrait, ScopeTrait;
}

View File

@@ -0,0 +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 OAuth2ServerExamples\Entities;
use League\OAuth2\Server\Entities\UserEntityInterface;
class UserEntity implements UserEntityInterface
{
/**
* Return the user's identifier.
*
* @return mixed
*/
public function getIdentifier()
{
return 1;
}
}

View File

@@ -0,0 +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\AccessTokenEntityInterface;
use League\OAuth2\Server\Entities\ClientEntityInterface;
use League\OAuth2\Server\Repositories\AccessTokenRepositoryInterface;
use OAuth2ServerExamples\Entities\AccessTokenEntity;
class AccessTokenRepository implements AccessTokenRepositoryInterface
{
/**
* {@inheritdoc}
*/
public function persistNewAccessToken(AccessTokenEntityInterface $accessTokenEntity)
{
// Some logic here to save the access token to a database
}
/**
* {@inheritdoc}
*/
public function revokeAccessToken($tokenId)
{
// Some logic here to revoke the access token
}
/**
* {@inheritdoc}
*/
public function isAccessTokenRevoked($tokenId)
{
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

@@ -0,0 +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\AuthCodeEntityInterface;
use League\OAuth2\Server\Repositories\AuthCodeRepositoryInterface;
use OAuth2ServerExamples\Entities\AuthCodeEntity;
class AuthCodeRepository implements AuthCodeRepositoryInterface
{
/**
* {@inheritdoc}
*/
public function persistNewAuthCode(AuthCodeEntityInterface $authCodeEntity)
{
// Some logic to persist the auth code to a database
}
/**
* {@inheritdoc}
*/
public function revokeAuthCode($codeId)
{
// Some logic to revoke the auth code in a database
}
/**
* {@inheritdoc}
*/
public function isAuthCodeRevoked($codeId)
{
return false; // The auth code has not been revoked
}
/**
* {@inheritdoc}
*/
public function getNewAuthCode()
{
return new AuthCodeEntity();
}
}

View File

@@ -0,0 +1,60 @@
<?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\Repositories\ClientRepositoryInterface;
use OAuth2ServerExamples\Entities\ClientEntity;
class ClientRepository implements ClientRepositoryInterface
{
const CLIENT_NAME = 'My Awesome App';
const REDIRECT_URI = 'http://foo/bar';
/**
* {@inheritdoc}
*/
public function getClientEntity($clientIdentifier)
{
$client = new ClientEntity();
$client->setIdentifier($clientIdentifier);
$client->setName(self::CLIENT_NAME);
$client->setRedirectUri(self::REDIRECT_URI);
return $client;
}
/**
* {@inheritdoc}
*/
public function validateClient($clientIdentifier, $clientSecret, $grantType)
{
$clients = [
'myawesomeapp' => [
'secret' => password_hash('abc123', PASSWORD_BCRYPT),
'name' => self::CLIENT_NAME,
'redirect_uri' => self::REDIRECT_URI,
'is_confidential' => true,
],
];
// Check if client is registered
if (array_key_exists($clientIdentifier, $clients) === false) {
return;
}
if (
$clients[$clientIdentifier]['is_confidential'] === true
&& password_verify($clientSecret, $clients[$clientIdentifier]['secret']) === false
) {
return;
}
}
}

View File

@@ -0,0 +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\RefreshTokenEntityInterface;
use League\OAuth2\Server\Repositories\RefreshTokenRepositoryInterface;
use OAuth2ServerExamples\Entities\RefreshTokenEntity;
class RefreshTokenRepository implements RefreshTokenRepositoryInterface
{
/**
* {@inheritdoc}
*/
public function persistNewRefreshToken(RefreshTokenEntityInterface $refreshTokenEntity)
{
// Some logic to persist the refresh token in a database
}
/**
* {@inheritdoc}
*/
public function revokeRefreshToken($tokenId)
{
// Some logic to revoke the refresh token in a database
}
/**
* {@inheritdoc}
*/
public function isRefreshTokenRevoked($tokenId)
{
return false; // The refresh token has not been revoked
}
/**
* {@inheritdoc}
*/
public function getNewRefreshToken()
{
return new RefreshTokenEntity();
}
}

View File

@@ -0,0 +1,60 @@
<?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\ClientEntityInterface;
use League\OAuth2\Server\Repositories\ScopeRepositoryInterface;
use OAuth2ServerExamples\Entities\ScopeEntity;
class ScopeRepository implements ScopeRepositoryInterface
{
/**
* {@inheritdoc}
*/
public function getScopeEntityByIdentifier($scopeIdentifier)
{
$scopes = [
'basic' => [
'description' => 'Basic details about you',
],
'email' => [
'description' => 'Your email address',
],
];
if (array_key_exists($scopeIdentifier, $scopes) === false) {
return;
}
$scope = new ScopeEntity();
$scope->setIdentifier($scopeIdentifier);
return $scope;
}
/**
* {@inheritdoc}
*/
public function finalizeScopes(
array $scopes,
$grantType,
ClientEntityInterface $clientEntity,
$userIdentifier = null
) {
// Example of programatically modifying the final scope of the access token
if ((int) $userIdentifier === 1) {
$scope = new ScopeEntity();
$scope->setIdentifier('email');
$scopes[] = $scope;
}
return $scopes;
}
}

View File

@@ -0,0 +1,33 @@
<?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\ClientEntityInterface;
use League\OAuth2\Server\Repositories\UserRepositoryInterface;
use OAuth2ServerExamples\Entities\UserEntity;
class UserRepository implements UserRepositoryInterface
{
/**
* {@inheritdoc}
*/
public function getUserEntityByUserCredentials(
$username,
$password,
$grantType,
ClientEntityInterface $clientEntity
) {
if ($username === 'alex' && $password === 'whisky') {
return new UserEntity();
}
return;
}
}

8
phpstan.neon Normal file
View File

@@ -0,0 +1,8 @@
includes:
- vendor/phpstan/phpstan-phpunit/extension.neon
- vendor/phpstan/phpstan-phpunit/rules.neon
services:
-
class: LeagueTests\PHPStan\AbstractGrantExtension
tags:
- phpstan.broker.dynamicMethodReturnTypeExtension

View File

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

24
phpunit.xml.dist Normal file
View File

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

View File

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

View File

@@ -1,295 +1,236 @@
<?php
/**
* OAuth 2.0 Authorization Server
*
* @package league/oauth2-server
* @author Alex Bilbie <hello@alexbilbie.com>
* @copyright Copyright (c) Alex Bilbie
* @license http://mit-license.org/
*
* @link https://github.com/thephpleague/oauth2-server
*/
namespace League\OAuth2\Server;
use DateInterval;
use Defuse\Crypto\Key;
use League\Event\EmitterAwareInterface;
use League\Event\EmitterAwareTrait;
use League\OAuth2\Server\Exception\OAuthServerException;
use League\OAuth2\Server\Grant\GrantTypeInterface;
use League\OAuth2\Server\TokenType\Bearer;
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\AbstractResponseType;
use League\OAuth2\Server\ResponseTypes\BearerTokenResponse;
use League\OAuth2\Server\ResponseTypes\ResponseTypeInterface;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
/**
* OAuth 2.0 authorization server class
*/
class AuthorizationServer extends AbstractServer
class AuthorizationServer implements EmitterAwareInterface
{
use EmitterAwareTrait;
/**
* @var GrantTypeInterface[]
*/
protected $enabledGrantTypes = [];
/**
* @var DateInterval[]
*/
protected $grantTypeAccessTokenTTL = [];
/**
* @var CryptKey
*/
protected $privateKey;
/**
* @var CryptKey
*/
protected $publicKey;
/**
* @var ResponseTypeInterface
*/
protected $responseType;
/**
* @var ClientRepositoryInterface
*/
private $clientRepository;
/**
* @var AccessTokenRepositoryInterface
*/
private $accessTokenRepository;
/**
* @var ScopeRepositoryInterface
*/
private $scopeRepository;
/**
* @var string|Key
*/
private $encryptionKey;
/**
* The delimiter between scopes specified in the scope query string parameter
* The OAuth 2 specification states it should be a space but most use a comma
*
* @var string
*/
protected $scopeDelimiter = ' ';
private $defaultScope = '';
/**
* The TTL (time to live) of an access token in seconds (default: 3600)
* New server instance.
*
* @var integer
* @param ClientRepositoryInterface $clientRepository
* @param AccessTokenRepositoryInterface $accessTokenRepository
* @param ScopeRepositoryInterface $scopeRepository
* @param CryptKey|string $privateKey
* @param string|Key $encryptionKey
* @param null|ResponseTypeInterface $responseType
*/
protected $accessTokenTTL = 3600;
public function __construct(
ClientRepositoryInterface $clientRepository,
AccessTokenRepositoryInterface $accessTokenRepository,
ScopeRepositoryInterface $scopeRepository,
$privateKey,
$encryptionKey,
ResponseTypeInterface $responseType = null
) {
$this->clientRepository = $clientRepository;
$this->accessTokenRepository = $accessTokenRepository;
$this->scopeRepository = $scopeRepository;
/**
* The registered grant response types
*
* @var array
*/
protected $responseTypes = [];
/**
* The registered grant types
*
* @var array
*/
protected $grantTypes = [];
/**
* Require the "scope" parameter to be in checkAuthoriseParams()
*
* @var boolean
*/
protected $requireScopeParam = false;
/**
* Default scope(s) to be used if none is provided
*
* @var string|array
*/
protected $defaultScope;
/**
* Require the "state" parameter to be in checkAuthoriseParams()
*
* @var boolean
*/
protected $requireStateParam = false;
/**
* Create a new OAuth2 authorization server
*
* @return self
*/
public function __construct()
{
// Set Bearer as the default token type
$this->setTokenType(new Bearer());
parent::__construct();
return $this;
}
/**
* Enable support for a grant
*
* @param GrantTypeInterface $grantType A grant class which conforms to Interface/GrantTypeInterface
* @param null|string $identifier An identifier for the grant (autodetected if not passed)
*
* @return self
*/
public function addGrantType(GrantTypeInterface $grantType, $identifier = null)
{
if (is_null($identifier)) {
$identifier = $grantType->getIdentifier();
if ($privateKey instanceof CryptKey === false) {
$privateKey = new CryptKey($privateKey);
}
// Inject server into grant
$grantType->setAuthorizationServer($this);
$this->privateKey = $privateKey;
$this->encryptionKey = $encryptionKey;
$this->grantTypes[$identifier] = $grantType;
if (!is_null($grantType->getResponseType())) {
$this->responseTypes[] = $grantType->getResponseType();
if ($responseType === null) {
$responseType = new BearerTokenResponse();
} else {
$responseType = clone $responseType;
}
return $this;
$this->responseType = $responseType;
}
/**
* Check if a grant type has been enabled
* Enable a grant type on the server.
*
* @param string $identifier The grant type identifier
*
* @return boolean Returns "true" if enabled, "false" if not
* @param GrantTypeInterface $grantType
* @param null|DateInterval $accessTokenTTL
*/
public function hasGrantType($identifier)
public function enableGrantType(GrantTypeInterface $grantType, DateInterval $accessTokenTTL = null)
{
return (array_key_exists($identifier, $this->grantTypes));
}
/**
* Returns response types
*
* @return array
*/
public function getResponseTypes()
{
return $this->responseTypes;
}
/**
* Require the "scope" parameter in checkAuthoriseParams()
*
* @param boolean $require
*
* @return self
*/
public function requireScopeParam($require = true)
{
$this->requireScopeParam = $require;
return $this;
}
/**
* Is the scope parameter required?
*
* @return bool
*/
public function scopeParamRequired()
{
return $this->requireScopeParam;
}
/**
* Default scope to be used if none is provided and requireScopeParam() is false
*
* @param string $default Name of the default scope
*
* @return self
*/
public function setDefaultScope($default = null)
{
$this->defaultScope = $default;
return $this;
}
/**
* Default scope to be used if none is provided and requireScopeParam is false
*
* @return string|null
*/
public function getDefaultScope()
{
return $this->defaultScope;
}
/**
* Require the "state" parameter in checkAuthoriseParams()
*
* @return bool
*/
public function stateParamRequired()
{
return $this->requireStateParam;
}
/**
* Require the "state" parameter in checkAuthoriseParams()
*
* @param boolean $require
*
* @return self
*/
public function requireStateParam($require = true)
{
$this->requireStateParam = $require;
return $this;
}
/**
* Get the scope delimiter
*
* @return string The scope delimiter (default: ",")
*/
public function getScopeDelimiter()
{
return $this->scopeDelimiter;
}
/**
* Set the scope delimiter
*
* @param string $scopeDelimiter
*
* @return self
*/
public function setScopeDelimiter($scopeDelimiter = ' ')
{
$this->scopeDelimiter = $scopeDelimiter;
return $this;
}
/**
* Get the TTL for an access token
*
* @return int The TTL
*/
public function getAccessTokenTTL()
{
return $this->accessTokenTTL;
}
/**
* Set the TTL for an access token
*
* @param int $accessTokenTTL The new TTL
*
* @return self
*/
public function setAccessTokenTTL($accessTokenTTL = 3600)
{
$this->accessTokenTTL = $accessTokenTTL;
return $this;
}
/**
* Issue an access token
*
* @return array Authorise request parameters
*
* @throws
*/
public function issueAccessToken()
{
$grantType = $this->getRequest()->request->get('grant_type');
if (is_null($grantType)) {
throw new Exception\InvalidRequestException('grant_type');
if ($accessTokenTTL === null) {
$accessTokenTTL = new DateInterval('PT1H');
}
// Ensure grant type is one that is recognised and is enabled
if (!in_array($grantType, array_keys($this->grantTypes))) {
throw new Exception\UnsupportedGrantTypeException($grantType);
}
$grantType->setAccessTokenRepository($this->accessTokenRepository);
$grantType->setClientRepository($this->clientRepository);
$grantType->setScopeRepository($this->scopeRepository);
$grantType->setDefaultScope($this->defaultScope);
$grantType->setPrivateKey($this->privateKey);
$grantType->setEmitter($this->getEmitter());
$grantType->setEncryptionKey($this->encryptionKey);
// Complete the flow
return $this->getGrantType($grantType)->completeFlow();
$this->enabledGrantTypes[$grantType->getIdentifier()] = $grantType;
$this->grantTypeAccessTokenTTL[$grantType->getIdentifier()] = $accessTokenTTL;
}
/**
* Return a grant type class
* Validate an authorization request
*
* @param string $grantType The grant type identifier
* @param ServerRequestInterface $request
*
* @return Grant\GrantTypeInterface
* @throws OAuthServerException
*
* @throws
* @return AuthorizationRequest
*/
public function getGrantType($grantType)
public function validateAuthorizationRequest(ServerRequestInterface $request)
{
if (isset($this->grantTypes[$grantType])) {
return $this->grantTypes[$grantType];
foreach ($this->enabledGrantTypes as $grantType) {
if ($grantType->canRespondToAuthorizationRequest($request)) {
return $grantType->validateAuthorizationRequest($request);
}
}
throw new Exception\InvalidGrantException($grantType);
throw OAuthServerException::unsupportedGrantType();
}
/**
* Complete an authorization request
*
* @param AuthorizationRequest $authRequest
* @param ResponseInterface $response
*
* @return ResponseInterface
*/
public function completeAuthorizationRequest(AuthorizationRequest $authRequest, ResponseInterface $response)
{
return $this->enabledGrantTypes[$authRequest->getGrantTypeId()]
->completeAuthorizationRequest($authRequest)
->generateHttpResponse($response);
}
/**
* Return an access token response.
*
* @param ServerRequestInterface $request
* @param ResponseInterface $response
*
* @throws OAuthServerException
*
* @return ResponseInterface
*/
public function respondToAccessTokenRequest(ServerRequestInterface $request, ResponseInterface $response)
{
foreach ($this->enabledGrantTypes as $grantType) {
if (!$grantType->canRespondToAccessTokenRequest($request)) {
continue;
}
$tokenResponse = $grantType->respondToAccessTokenRequest(
$request,
$this->getResponseType(),
$this->grantTypeAccessTokenTTL[$grantType->getIdentifier()]
);
if ($tokenResponse instanceof ResponseTypeInterface) {
return $tokenResponse->generateHttpResponse($response);
}
}
throw OAuthServerException::unsupportedGrantType();
}
/**
* Get the token type that grants will return in the HTTP response.
*
* @return ResponseTypeInterface
*/
protected function getResponseType()
{
$responseType = clone $this->responseType;
if ($responseType instanceof AbstractResponseType) {
$responseType->setPrivateKey($this->privateKey);
}
$responseType->setEncryptionKey($this->encryptionKey);
return $responseType;
}
/**
* Set the default scope for the authorization server.
*
* @param string $defaultScope
*/
public function setDefaultScope($defaultScope)
{
$this->defaultScope = $defaultScope;
}
}

View File

@@ -0,0 +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\AuthorizationValidators;
use Psr\Http\Message\ServerRequestInterface;
interface AuthorizationValidatorInterface
{
/**
* Determine the access token in the authorization header and append OAUth properties to the request
* as attributes.
*
* @param ServerRequestInterface $request
*
* @return ServerRequestInterface
*/
public function validateAuthorization(ServerRequestInterface $request);
}

View File

@@ -0,0 +1,106 @@
<?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 BadMethodCallException;
use InvalidArgumentException;
use Lcobucci\JWT\Parser;
use Lcobucci\JWT\Signer\Rsa\Sha256;
use Lcobucci\JWT\ValidationData;
use League\OAuth2\Server\CryptKey;
use League\OAuth2\Server\CryptTrait;
use League\OAuth2\Server\Exception\OAuthServerException;
use League\OAuth2\Server\Repositories\AccessTokenRepositoryInterface;
use Psr\Http\Message\ServerRequestInterface;
use RuntimeException;
class BearerTokenValidator implements AuthorizationValidatorInterface
{
use CryptTrait;
/**
* @var AccessTokenRepositoryInterface
*/
private $accessTokenRepository;
/**
* @var CryptKey
*/
protected $publicKey;
/**
* @param AccessTokenRepositoryInterface $accessTokenRepository
*/
public function __construct(AccessTokenRepositoryInterface $accessTokenRepository)
{
$this->accessTokenRepository = $accessTokenRepository;
}
/**
* Set the public key
*
* @param CryptKey $key
*/
public function setPublicKey(CryptKey $key)
{
$this->publicKey = $key;
}
/**
* {@inheritdoc}
*/
public function validateAuthorization(ServerRequestInterface $request)
{
if ($request->hasHeader('authorization') === false) {
throw OAuthServerException::accessDenied('Missing "Authorization" header');
}
$header = $request->getHeader('authorization');
$jwt = trim((string) preg_replace('/^(?:\s+)?Bearer\s/', '', $header[0]));
try {
// Attempt to parse and validate the JWT
$token = (new Parser())->parse($jwt);
try {
if ($token->verify(new Sha256(), $this->publicKey->getKeyPath()) === false) {
throw OAuthServerException::accessDenied('Access token could not be verified');
}
} catch (BadMethodCallException $exception) {
throw OAuthServerException::accessDenied('Access token is not signed', null, $exception);
}
// 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');
}
// Return the request with additional attributes
return $request
->withAttribute('oauth_access_token_id', $token->getClaim('jti'))
->withAttribute('oauth_client_id', $token->getClaim('aud'))
->withAttribute('oauth_user_id', $token->getClaim('sub'))
->withAttribute('oauth_scopes', $token->getClaim('scopes'));
} catch (InvalidArgumentException $exception) {
// JWT couldn't be parsed so return the request as is
throw OAuthServerException::accessDenied($exception->getMessage(), null, $exception);
} catch (RuntimeException $exception) {
//JWR couldn't be parsed so return the request as is
throw OAuthServerException::accessDenied('Error while decoding to JSON', null, $exception);
}
}
}

View File

@@ -0,0 +1,30 @@
<?php
/**
* @author Lukáš Unger <lookymsc@gmail.com>
* @copyright Copyright (c) Lukáš Unger
* @license http://mit-license.org/
*
* @link https://github.com/thephpleague/oauth2-server
*/
namespace League\OAuth2\Server\CodeChallengeVerifiers;
interface CodeChallengeVerifierInterface
{
/**
* Return code challenge method.
*
* @return string
*/
public function getMethod();
/**
* Verify the code challenge.
*
* @param string $codeVerifier
* @param string $codeChallenge
*
* @return bool
*/
public function verifyCodeChallenge($codeVerifier, $codeChallenge);
}

View File

@@ -0,0 +1,36 @@
<?php
/**
* @author Lukáš Unger <lookymsc@gmail.com>
* @copyright Copyright (c) Lukáš Unger
* @license http://mit-license.org/
*
* @link https://github.com/thephpleague/oauth2-server
*/
namespace League\OAuth2\Server\CodeChallengeVerifiers;
class PlainVerifier implements CodeChallengeVerifierInterface
{
/**
* Return code challenge method.
*
* @return string
*/
public function getMethod()
{
return 'plain';
}
/**
* Verify the code challenge.
*
* @param string $codeVerifier
* @param string $codeChallenge
*
* @return bool
*/
public function verifyCodeChallenge($codeVerifier, $codeChallenge)
{
return hash_equals($codeVerifier, $codeChallenge);
}
}

View File

@@ -0,0 +1,39 @@
<?php
/**
* @author Lukáš Unger <lookymsc@gmail.com>
* @copyright Copyright (c) Lukáš Unger
* @license http://mit-license.org/
*
* @link https://github.com/thephpleague/oauth2-server
*/
namespace League\OAuth2\Server\CodeChallengeVerifiers;
class S256Verifier implements CodeChallengeVerifierInterface
{
/**
* Return code challenge method.
*
* @return string
*/
public function getMethod()
{
return 'S256';
}
/**
* Verify the code challenge.
*
* @param string $codeVerifier
* @param string $codeChallenge
*
* @return bool
*/
public function verifyCodeChallenge($codeVerifier, $codeChallenge)
{
return hash_equals(
strtr(rtrim(base64_encode(hash('sha256', $codeVerifier, true)), '='), '+/', '-_'),
$codeChallenge
);
}
}

123
src/CryptKey.php Normal file
View File

@@ -0,0 +1,123 @@
<?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;
use LogicException;
use RuntimeException;
class CryptKey
{
const RSA_KEY_PATTERN =
'/^(-----BEGIN (RSA )?(PUBLIC|PRIVATE) KEY-----)\R.*(-----END (RSA )?(PUBLIC|PRIVATE) KEY-----)\R?$/s';
/**
* @var string
*/
protected $keyPath;
/**
* @var null|string
*/
protected $passPhrase;
/**
* @param string $keyPath
* @param null|string $passPhrase
* @param bool $keyPermissionsCheck
*/
public function __construct($keyPath, $passPhrase = null, $keyPermissionsCheck = true)
{
if (preg_match(self::RSA_KEY_PATTERN, $keyPath)) {
$keyPath = $this->saveKeyToFile($keyPath);
}
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));
}
if ($keyPermissionsCheck === true) {
// Verify the permissions of the key
$keyPathPerms = decoct(fileperms($keyPath) & 0777);
if (in_array($keyPathPerms, ['400', '440', '600', '640', '660'], true) === false) {
trigger_error(sprintf(
'Key file "%s" permissions are not correct, recommend changing to 600 or 660 instead of %s',
$keyPath,
$keyPathPerms
), E_USER_NOTICE);
}
}
$this->keyPath = $keyPath;
$this->passPhrase = $passPhrase;
}
/**
* @param string $key
*
* @throws RuntimeException
*
* @return string
*/
private function saveKeyToFile($key)
{
$tmpDir = sys_get_temp_dir();
$keyPath = $tmpDir . '/' . sha1($key) . '.key';
if (file_exists($keyPath)) {
return 'file://' . $keyPath;
}
if (!touch($keyPath)) {
// @codeCoverageIgnoreStart
throw new RuntimeException(sprintf('"%s" key file could not be created', $keyPath));
// @codeCoverageIgnoreEnd
}
if (file_put_contents($keyPath, $key) === false) {
// @codeCoverageIgnoreStart
throw new RuntimeException(sprintf('Unable to write key file to temporary directory "%s"', $tmpDir));
// @codeCoverageIgnoreEnd
}
if (chmod($keyPath, 0600) === false) {
// @codeCoverageIgnoreStart
throw new RuntimeException(sprintf('The key file "%s" file mode could not be changed with chmod to 600', $keyPath));
// @codeCoverageIgnoreEnd
}
return 'file://' . $keyPath;
}
/**
* Retrieve key path.
*
* @return string
*/
public function getKeyPath()
{
return $this->keyPath;
}
/**
* Retrieve key pass phrase.
*
* @return null|string
*/
public function getPassPhrase()
{
return $this->passPhrase;
}
}

87
src/CryptTrait.php Normal file
View File

@@ -0,0 +1,87 @@
<?php
/**
* Encrypt/decrypt with encryptionKey.
*
* @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 Defuse\Crypto\Crypto;
use Defuse\Crypto\Key;
use Exception;
use LogicException;
trait CryptTrait
{
/**
* @var string|Key|null
*/
protected $encryptionKey;
/**
* Encrypt data with encryptionKey.
*
* @param string $unencryptedData
*
* @throws LogicException
*
* @return string
*/
protected function encrypt($unencryptedData)
{
try {
if ($this->encryptionKey instanceof Key) {
return Crypto::encrypt($unencryptedData, $this->encryptionKey);
}
if (is_string($this->encryptionKey)) {
return Crypto::encryptWithPassword($unencryptedData, $this->encryptionKey);
}
throw new LogicException('Encryption key not set when attempting to encrypt');
} catch (Exception $e) {
throw new LogicException($e->getMessage(), 0, $e);
}
}
/**
* Decrypt data with encryptionKey.
*
* @param string $encryptedData
*
* @throws LogicException
*
* @return string
*/
protected function decrypt($encryptedData)
{
try {
if ($this->encryptionKey instanceof Key) {
return Crypto::decrypt($encryptedData, $this->encryptionKey);
}
if (is_string($this->encryptionKey)) {
return Crypto::decryptWithPassword($encryptedData, $this->encryptionKey);
}
throw new LogicException('Encryption key not set when attempting to decrypt');
} catch (Exception $e) {
throw new LogicException($e->getMessage(), 0, $e);
}
}
/**
* Set the encryption key
*
* @param string|Key $key
*/
public function setEncryptionKey($key = null)
{
$this->encryptionKey = $key;
}
}

View File

@@ -0,0 +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\Entities;
use League\OAuth2\Server\CryptKey;
interface AccessTokenEntityInterface extends TokenInterface
{
/**
* Set a private key used to encrypt the access token.
*/
public function setPrivateKey(CryptKey $privateKey);
/**
* Generate a string representation of the access token.
*/
public function __toString();
}

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|null
*/
public function getRedirectUri();
/**
* @param string $uri
*/
public function setRedirectUri($uri);
}

View File

@@ -0,0 +1,43 @@
<?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();
/**
* Returns true if the client is confidential.
*
* @return bool
*/
public function isConfidential();
}

View File

@@ -0,0 +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 League\OAuth2\Server\Entities;
use DateTimeImmutable;
interface RefreshTokenEntityInterface
{
/**
* Get the token's identifier.
*
* @return string
*/
public function getIdentifier();
/**
* Set the token's identifier.
*
* @param mixed $identifier
*/
public function setIdentifier($identifier);
/**
* Get the token's expiry date time.
*
* @return DateTimeImmutable
*/
public function getExpiryDateTime();
/**
* Set the date time when the token expires.
*
* @param DateTimeImmutable $dateTime
*/
public function setExpiryDateTime(DateTimeImmutable $dateTime);
/**
* Set the access token that the refresh token was associated with.
*
* @param AccessTokenEntityInterface $accessToken
*/
public function setAccessToken(AccessTokenEntityInterface $accessToken);
/**
* Get the access token that the refresh token was originally associated with.
*
* @return AccessTokenEntityInterface
*/
public function getAccessToken();
}

View File

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

View File

@@ -0,0 +1,85 @@
<?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 DateTimeImmutable;
interface TokenInterface
{
/**
* Get the token's identifier.
*
* @return string
*/
public function getIdentifier();
/**
* Set the token's identifier.
*
* @param mixed $identifier
*/
public function setIdentifier($identifier);
/**
* Get the token's expiry date time.
*
* @return DateTimeImmutable
*/
public function getExpiryDateTime();
/**
* Set the date time when the token expires.
*
* @param DateTimeImmutable $dateTime
*/
public function setExpiryDateTime(DateTimeImmutable $dateTime);
/**
* Set the identifier of the user associated with the token.
*
* @param string|int|null $identifier The identifier of the user
*/
public function setUserIdentifier($identifier);
/**
* Get the token user's identifier.
*
* @return string|int|null
*/
public function getUserIdentifier();
/**
* Get the client that the token was issued to.
*
* @return ClientEntityInterface
*/
public function getClient();
/**
* Set the client that the token was issued to.
*
* @param ClientEntityInterface $client
*/
public function setClient(ClientEntityInterface $client);
/**
* Associate a scope with the token.
*
* @param ScopeEntityInterface $scope
*/
public function addScope(ScopeEntityInterface $scope);
/**
* Return an array of scopes associated with the token.
*
* @return ScopeEntityInterface[]
*/
public function getScopes();
}

View File

@@ -0,0 +1,84 @@
<?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 DateTimeImmutable;
use Lcobucci\JWT\Builder;
use Lcobucci\JWT\Signer\Key;
use Lcobucci\JWT\Signer\Rsa\Sha256;
use Lcobucci\JWT\Token;
use League\OAuth2\Server\CryptKey;
use League\OAuth2\Server\Entities\ClientEntityInterface;
use League\OAuth2\Server\Entities\ScopeEntityInterface;
trait AccessTokenTrait
{
/**
* @var CryptKey
*/
private $privateKey;
/**
* Set the private key used to encrypt this access token.
*/
public function setPrivateKey(CryptKey $privateKey)
{
$this->privateKey = $privateKey;
}
/**
* Generate a JWT from the access token
*
* @param CryptKey $privateKey
*
* @return Token
*/
private function convertToJWT(CryptKey $privateKey)
{
return (new Builder())
->setAudience($this->getClient()->getIdentifier())
->setId($this->getIdentifier())
->setIssuedAt(time())
->setNotBefore(time())
->setExpiration($this->getExpiryDateTime()->getTimestamp())
->setSubject((string) $this->getUserIdentifier())
->set('scopes', $this->getScopes())
->sign(new Sha256(), new Key($privateKey->getKeyPath(), $privateKey->getPassPhrase()))
->getToken();
}
/**
* Generate a string representation from the access token
*/
public function __toString()
{
return (string) $this->convertToJWT($this->privateKey);
}
/**
* @return ClientEntityInterface
*/
abstract public function getClient();
/**
* @return DateTimeImmutable
*/
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|null
*/
public function getRedirectUri()
{
return $this->redirectUri;
}
/**
* @param string $uri
*/
public function setRedirectUri($uri)
{
$this->redirectUri = $uri;
}
}

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;
trait ClientTrait
{
/**
* @var string
*/
protected $name;
/**
* @var string|string[]
*/
protected $redirectUri;
/**
* @var bool
*/
protected $isConfidential = false;
/**
* 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;
}
/**
* Returns true if the client is confidential.
*
* @return bool
*/
public function isConfidential()
{
return $this->isConfidential;
}
}

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 EntityTrait
{
/**
* @var string
*/
protected $identifier;
/**
* @return mixed
*/
public function getIdentifier()
{
return $this->identifier;
}
/**
* @param mixed $identifier
*/
public function setIdentifier($identifier)
{
$this->identifier = $identifier;
}
}

View File

@@ -0,0 +1,62 @@
<?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 DateTimeImmutable;
use League\OAuth2\Server\Entities\AccessTokenEntityInterface;
trait RefreshTokenTrait
{
/**
* @var AccessTokenEntityInterface
*/
protected $accessToken;
/**
* @var DateTimeImmutable
*/
protected $expiryDateTime;
/**
* {@inheritdoc}
*/
public function setAccessToken(AccessTokenEntityInterface $accessToken)
{
$this->accessToken = $accessToken;
}
/**
* {@inheritdoc}
*/
public function getAccessToken()
{
return $this->accessToken;
}
/**
* Get the token's expiry date time.
*
* @return DateTimeImmutable
*/
public function getExpiryDateTime()
{
return $this->expiryDateTime;
}
/**
* Set the date time when the token expires.
*
* @param DateTimeImmutable $dateTime
*/
public function setExpiryDateTime(DateTimeImmutable $dateTime)
{
$this->expiryDateTime = $dateTime;
}
}

View File

@@ -0,0 +1,28 @@
<?php
/**
* @author Andrew Millington <andrew@noexceptions.io>
* @copyright Copyright (c) Andrew Millington
* @license http://mit-license.org
*
* @link https://github.com/thephpleague/oauth2-server
*/
namespace League\OAuth2\Server\Entities\Traits;
trait ScopeTrait
{
/**
* Serialize the object to the scopes string identifier when using json_encode().
*
* @return string
*/
public function jsonSerialize()
{
return $this->getIdentifier();
}
/**
* @return string
*/
abstract public function getIdentifier();
}

View File

@@ -0,0 +1,117 @@
<?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 DateTimeImmutable;
use League\OAuth2\Server\Entities\ClientEntityInterface;
use League\OAuth2\Server\Entities\ScopeEntityInterface;
trait TokenEntityTrait
{
/**
* @var ScopeEntityInterface[]
*/
protected $scopes = [];
/**
* @var DateTimeImmutable
*/
protected $expiryDateTime;
/**
* @var string|int|null
*/
protected $userIdentifier;
/**
* @var ClientEntityInterface
*/
protected $client;
/**
* Associate a scope with the token.
*
* @param ScopeEntityInterface $scope
*/
public function addScope(ScopeEntityInterface $scope)
{
$this->scopes[$scope->getIdentifier()] = $scope;
}
/**
* Return an array of scopes associated with the token.
*
* @return ScopeEntityInterface[]
*/
public function getScopes()
{
return array_values($this->scopes);
}
/**
* Get the token's expiry date time.
*
* @return DateTimeImmutable
*/
public function getExpiryDateTime()
{
return $this->expiryDateTime;
}
/**
* Set the date time when the token expires.
*
* @param DateTimeImmutable $dateTime
*/
public function setExpiryDateTime(DateTimeImmutable $dateTime)
{
$this->expiryDateTime = $dateTime;
}
/**
* Set the identifier of the user associated with the token.
*
* @param string|int|null $identifier The identifier of the user
*/
public function setUserIdentifier($identifier)
{
$this->userIdentifier = $identifier;
}
/**
* Get the token user's identifier.
*
* @return string|int|null
*/
public function getUserIdentifier()
{
return $this->userIdentifier;
}
/**
* Get the client that the token was issued to.
*
* @return ClientEntityInterface
*/
public function getClient()
{
return $this->client;
}
/**
* Set the client that the token was issued to.
*
* @param ClientEntityInterface $client
*/
public function setClient(ClientEntityInterface $client)
{
$this->client = $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,209 +0,0 @@
<?php
/**
* OAuth 2.0 Abstract token
*
* @package league/oauth2-server
* @author Alex Bilbie <hello@alexbilbie.com>
* @copyright Copyright (c) Alex Bilbie
* @license http://mit-license.org/
* @link https://github.com/thephpleague/oauth2-server
*/
namespace League\OAuth2\Server\Entity;
use League\OAuth2\Server\AbstractServer;
use League\OAuth2\Server\Util\SecureKey;
/**
* Abstract token class
*/
abstract class AbstractTokenEntity
{
/**
* Token identifier
*
* @var string
*/
protected $id;
/**
* Associated session
*
* @var \League\OAuth2\Server\Entity\SessionEntity
*/
protected $session;
/**
* Session scopes
*
* @var \League\OAuth2\Server\Entity\ScopeEntity[]
*/
protected $scopes;
/**
* Token expire time
*
* @var int
*/
protected $expireTime = 0;
/**
* Authorization or resource server
*
* @var \League\OAuth2\Server\AbstractServer
*/
protected $server;
/**
* __construct
*
* @param \League\OAuth2\Server\AbstractServer $server
*
* @return self
*/
public function __construct(AbstractServer $server)
{
$this->server = $server;
return $this;
}
/**
* Set session
*
* @param \League\OAuth2\Server\Entity\SessionEntity $session
*
* @return self
*/
public function setSession(SessionEntity $session)
{
$this->session = $session;
return $this;
}
/**
* Set the expire time of the token
*
* @param integer $expireTime Unix time stamp
*
* @return self
*/
public function setExpireTime($expireTime)
{
$this->expireTime = $expireTime;
return $this;
}
/**
* Return token expire time
*
* @return int
*/
public function getExpireTime()
{
return $this->expireTime;
}
/**
* Is the token expired?
*
* @return bool
*/
public function isExpired()
{
return ((time() - $this->expireTime) > 0);
}
/**
* Set token ID
*
* @param string $id Token ID
*
* @return self
*/
public function setId($id = null)
{
$this->id = ($id !== null) ? $id : SecureKey::generate();
return $this;
}
/**
* Get the token ID
*
* @return string
*/
public function getId()
{
return $this->id;
}
/**
* Associate a scope
*
* @param \League\OAuth2\Server\Entity\ScopeEntity $scope
*
* @return self
*/
public function associateScope(ScopeEntity $scope)
{
if (!isset($this->scopes[$scope->getId()])) {
$this->scopes[$scope->getId()] = $scope;
}
return $this;
}
/**
* Format the local scopes array
*
* @param \League\OAuth2\Server\Entity\ScopeEntity[]
*
* @return array
*/
protected function formatScopes($unformatted = [])
{
if (is_null($unformatted)) {
return [];
}
$scopes = [];
foreach ($unformatted as $scope) {
if ($scope instanceof ScopeEntity) {
$scopes[$scope->getId()] = $scope;
}
}
return $scopes;
}
/**
* Returns the token as a string if the object is cast as a string
*
* @return string
*/
public function __toString()
{
if ($this->id === null) {
return '';
}
return $this->id;
}
/**
* Expire the token
*
* @return void
*/
abstract public function expire();
/**
* Save the token
*
* @return void
*/
abstract public function save();
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -1,43 +0,0 @@
<?php
/**
* OAuth 2.0 Invalid Grant Exception
*
* @package league/oauth2-server
* @author Alex Bilbie <hello@alexbilbie.com>
* @copyright Copyright (c) Alex Bilbie
* @license http://mit-license.org/
* @link https://github.com/thephpleague/oauth2-server
*/
namespace League\OAuth2\Server\Exception;
/**
* Exception class
*/
class InvalidGrantException extends OAuthException
{
/**
* {@inheritdoc}
*/
public $httpStatusCode = 400;
/**
* {@inheritdoc}
*/
public $errorType = 'invalid_grant';
/**
* {@inheritdoc}
*/
public function __construct($parameter)
{
$this->parameter = $parameter;
parent::__construct(
sprintf(
'The provided authorization grant is invalid, expired, revoked, does not match the redirection URI used in the authorization request, or was issued to another client. Check the "%s" parameter.',
$parameter
)
);
}
}

View File

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

View File

@@ -1,45 +0,0 @@
<?php
/**
* OAuth 2.0 Invalid Request Exception
*
* @package league/oauth2-server
* @author Alex Bilbie <hello@alexbilbie.com>
* @copyright Copyright (c) Alex Bilbie
* @license http://mit-license.org/
* @link https://github.com/thephpleague/oauth2-server
*/
namespace League\OAuth2\Server\Exception;
/**
* Exception class
*/
class InvalidRequestException extends OAuthException
{
/**
* {@inheritdoc}
*/
public $httpStatusCode = 400;
/**
* {@inheritdoc}
*/
public $errorType = 'invalid_request';
/**
* {@inheritdoc}
*/
public function __construct($parameter, $redirectUri = null)
{
$this->parameter = $parameter;
parent::__construct(
sprintf(
'The request is missing a required parameter, includes an invalid parameter value, includes a parameter more than once, or is otherwise malformed. Check the "%s" parameter.',
$parameter
)
);
$this->redirectUri = $redirectUri;
}
}

View File

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

View File

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

View File

@@ -0,0 +1,399 @@
<?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;
use Exception;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Throwable;
class OAuthServerException extends Exception
{
/**
* @var int
*/
private $httpStatusCode;
/**
* @var string
*/
private $errorType;
/**
* @var null|string
*/
private $hint;
/**
* @var null|string
*/
private $redirectUri;
/**
* @var array
*/
private $payload;
/**
* @var ServerRequestInterface
*/
private $serverRequest;
/**
* Throw a new exception.
*
* @param string $message Error message
* @param int $code Error code
* @param string $errorType Error type
* @param int $httpStatusCode HTTP status code to send (default = 400)
* @param null|string $hint A helper hint
* @param null|string $redirectUri A HTTP URI to redirect the user back to
* @param Throwable $previous Previous exception
*/
public function __construct($message, $code, $errorType, $httpStatusCode = 400, $hint = null, $redirectUri = null, Throwable $previous = null)
{
parent::__construct($message, $code, $previous);
$this->httpStatusCode = $httpStatusCode;
$this->errorType = $errorType;
$this->hint = $hint;
$this->redirectUri = $redirectUri;
$this->payload = [
'error' => $errorType,
'error_description' => $message,
];
if ($hint !== null) {
$this->payload['hint'] = $hint;
}
}
/**
* Returns the current payload.
*
* @return array
*/
public function getPayload()
{
$payload = $this->payload;
// The "message" property is deprecated and replaced by "error_description"
// TODO: remove "message" property
if (isset($payload['error_description']) && !isset($payload['message'])) {
$payload['message'] = $payload['error_description'];
}
return $payload;
}
/**
* Updates the current payload.
*
* @param array $payload
*/
public function setPayload(array $payload)
{
$this->payload = $payload;
}
/**
* Set the server request that is responsible for generating the exception
*
* @param ServerRequestInterface $serverRequest
*/
public function setServerRequest(ServerRequestInterface $serverRequest)
{
$this->serverRequest = $serverRequest;
}
/**
* Unsupported grant type error.
*
* @return static
*/
public static function unsupportedGrantType()
{
$errorMessage = 'The authorization grant type is not supported by the authorization server.';
$hint = 'Check that all required parameters have been provided';
return new static($errorMessage, 2, 'unsupported_grant_type', 400, $hint);
}
/**
* Invalid request error.
*
* @param string $parameter The invalid parameter
* @param null|string $hint
* @param Throwable $previous Previous exception
*
* @return static
*/
public static function invalidRequest($parameter, $hint = null, Throwable $previous = null)
{
$errorMessage = 'The request is missing a required parameter, includes an invalid parameter value, ' .
'includes a parameter more than once, or is otherwise malformed.';
$hint = ($hint === null) ? sprintf('Check the `%s` parameter', $parameter) : $hint;
return new static($errorMessage, 3, 'invalid_request', 400, $hint, null, $previous);
}
/**
* Invalid client error.
*
* @param ServerRequestInterface $serverRequest
*
* @return static
*/
public static function invalidClient(ServerRequestInterface $serverRequest)
{
$exception = new static('Client authentication failed', 4, 'invalid_client', 401);
$exception->setServerRequest($serverRequest);
return $exception;
}
/**
* Invalid scope error.
*
* @param string $scope The bad scope
* @param null|string $redirectUri A HTTP URI to redirect the user back to
*
* @return static
*/
public static function invalidScope($scope, $redirectUri = null)
{
$errorMessage = 'The requested scope is invalid, unknown, or malformed';
if (empty($scope)) {
$hint = 'Specify a scope in the request or set a default scope';
} else {
$hint = sprintf(
'Check the `%s` scope',
htmlspecialchars($scope, ENT_QUOTES, 'UTF-8', false)
);
}
return new static($errorMessage, 5, 'invalid_scope', 400, $hint, $redirectUri);
}
/**
* Invalid credentials error.
*
* @return static
*/
public static function invalidCredentials()
{
return new static('The user credentials were incorrect.', 6, 'invalid_credentials', 401);
}
/**
* Server error.
*
* @param string $hint
* @param Throwable $previous
*
* @return static
*
* @codeCoverageIgnore
*/
public static function serverError($hint, Throwable $previous = null)
{
return new static(
'The authorization server encountered an unexpected condition which prevented it from fulfilling'
. ' the request: ' . $hint,
7,
'server_error',
500,
null,
null,
$previous
);
}
/**
* Invalid refresh token.
*
* @param null|string $hint
* @param Throwable $previous
*
* @return static
*/
public static function invalidRefreshToken($hint = null, Throwable $previous = null)
{
return new static('The refresh token is invalid.', 8, 'invalid_request', 401, $hint, null, $previous);
}
/**
* Access denied.
*
* @param null|string $hint
* @param null|string $redirectUri
* @param Throwable $previous
*
* @return static
*/
public static function accessDenied($hint = null, $redirectUri = null, Throwable $previous = null)
{
return new static(
'The resource owner or authorization server denied the request.',
9,
'access_denied',
401,
$hint,
$redirectUri,
$previous
);
}
/**
* Invalid grant.
*
* @param string $hint
*
* @return static
*/
public static function invalidGrant($hint = '')
{
return new static(
'The provided authorization grant (e.g., authorization code, resource owner credentials) or refresh token '
. 'is invalid, expired, revoked, does not match the redirection URI used in the authorization request, '
. 'or was issued to another client.',
10,
'invalid_grant',
400,
$hint
);
}
/**
* @return string
*/
public function getErrorType()
{
return $this->errorType;
}
/**
* Generate a HTTP response.
*
* @param ResponseInterface $response
* @param bool $useFragment True if errors should be in the URI fragment instead of query string
* @param int $jsonOptions options passed to json_encode
*
* @return ResponseInterface
*/
public function generateHttpResponse(ResponseInterface $response, $useFragment = false, $jsonOptions = 0)
{
$headers = $this->getHttpHeaders();
$payload = $this->getPayload();
$redirectUri = $this->getRedirectUri($useFragment);
if ($redirectUri !== null) {
return $response->withStatus(302)->withHeader('Location', $redirectUri);
}
foreach ($headers as $header => $content) {
$response = $response->withHeader($header, $content);
}
$responseBody = json_encode($payload, $jsonOptions) ?: 'JSON encoding of payload failed';
$response->getBody()->write($responseBody);
return $response->withStatus($this->getHttpStatusCode());
}
/**
* Get all headers that have to be send with the error response.
*
* @return array Array with header values
*/
public function getHttpHeaders()
{
$headers = [
'Content-type' => 'application/json',
];
// Add "WWW-Authenticate" header
//
// RFC 6749, section 5.2.:
// "If the client attempted to authenticate via the 'Authorization'
// request header field, the authorization server MUST
// respond with an HTTP 401 (Unauthorized) status code and
// include the "WWW-Authenticate" response header field
// matching the authentication scheme used by the client.
// @codeCoverageIgnoreStart
if ($this->errorType === 'invalid_client' && $this->serverRequest->hasHeader('Authorization') === true) {
$authScheme = strpos($this->serverRequest->getHeader('Authorization')[0], 'Bearer') === 0 ? 'Bearer' : 'Basic';
$headers['WWW-Authenticate'] = $authScheme . ' realm="OAuth"';
}
// @codeCoverageIgnoreEnd
return $headers;
}
/**
* Check if the exception has an associated redirect URI.
*
* Returns whether the exception includes a redirect, since
* getHttpStatusCode() doesn't return a 302 when there's a
* redirect enabled. This helps when you want to override local
* error pages but want to let redirects through.
*
* @return bool
*/
public function hasRedirect()
{
return $this->redirectUri !== null;
}
/**
* Returns the redirectUri with all necessary args.
*
* Null will be returned if the exception doesn't contain the redirectUri.
*
* @param bool $useFragment True if errors should be in the URI fragment instead of query string
*
* @return string|null
*/
public function getRedirectUri(bool $useFragment = false): ?string
{
if ($this->redirectUri === null) {
return null;
}
$redirectUri = $this->redirectUri;
if ($useFragment) {
$redirectUri .= strpos($this->redirectUri, '#') === false ? '#' : '&';
} else {
$redirectUri .= strpos($this->redirectUri, '?') === false ? '?' : '&';
}
return $redirectUri . http_build_query($this->getPayload());
}
/**
* Returns the HTTP status code to send when the exceptions is output.
*
* @return int
*/
public function getHttpStatusCode()
{
return $this->httpStatusCode;
}
/**
* @return null|string
*/
public function getHint()
{
return $this->hint;
}
}

View File

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

View File

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

View File

@@ -0,0 +1,23 @@
<?php
/**
* @author Ivan Kurnosov <zerkms@zerkms.com>
* @copyright Copyright (c) Alex Bilbie
* @license http://mit-license.org/
*
* @link https://github.com/thephpleague/oauth2-server
*/
namespace League\OAuth2\Server\Exception;
class UniqueTokenIdentifierConstraintViolationException extends OAuthServerException
{
/**
* @return UniqueTokenIdentifierConstraintViolationException
*/
public static function create()
{
$errorMessage = 'Could not create unique access token identifier';
return new static($errorMessage, 100, 'access_token_duplicate', 500);
}
}

View File

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

View File

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

View File

@@ -0,0 +1,29 @@
<?php
/**
* Abstract authorization grant.
*
* @author Julián Gutiérrez <juliangut@gmail.com>
* @copyright Copyright (c) Alex Bilbie
* @license http://mit-license.org/
*
* @link https://github.com/thephpleague/oauth2-server
*/
namespace League\OAuth2\Server\Grant;
abstract class AbstractAuthorizeGrant extends AbstractGrant
{
/**
* @param string $uri
* @param array $params
* @param string $queryDelimiter
*
* @return string
*/
public function makeRedirectUri($uri, $params = [], $queryDelimiter = '?')
{
$uri .= (strstr($uri, $queryDelimiter) === false) ? $queryDelimiter : '&';
return $uri . http_build_query($params);
}
}

View File

@@ -1,197 +1,599 @@
<?php
/**
* OAuth 2.0 Abstract grant
* OAuth 2.0 Abstract grant.
*
* @package league/oauth2-server
* @author Alex Bilbie <hello@alexbilbie.com>
* @copyright Copyright (c) Alex Bilbie
* @license http://mit-license.org/
*
* @link https://github.com/thephpleague/oauth2-server
*/
namespace League\OAuth2\Server\Grant;
use League\OAuth2\Server\AuthorizationServer;
use League\OAuth2\Server\Entity\ClientEntity;
use League\OAuth2\Server\Entity\ScopeEntity;
use League\OAuth2\Server\Exception;
use DateInterval;
use DateTimeImmutable;
use Error;
use Exception;
use League\Event\EmitterAwareTrait;
use League\OAuth2\Server\CryptKey;
use League\OAuth2\Server\CryptTrait;
use League\OAuth2\Server\Entities\AccessTokenEntityInterface;
use League\OAuth2\Server\Entities\AuthCodeEntityInterface;
use League\OAuth2\Server\Entities\ClientEntityInterface;
use League\OAuth2\Server\Entities\RefreshTokenEntityInterface;
use League\OAuth2\Server\Entities\ScopeEntityInterface;
use League\OAuth2\Server\Exception\OAuthServerException;
use League\OAuth2\Server\Exception\UniqueTokenIdentifierConstraintViolationException;
use League\OAuth2\Server\Repositories\AccessTokenRepositoryInterface;
use League\OAuth2\Server\Repositories\AuthCodeRepositoryInterface;
use League\OAuth2\Server\Repositories\ClientRepositoryInterface;
use League\OAuth2\Server\Repositories\RefreshTokenRepositoryInterface;
use League\OAuth2\Server\Repositories\ScopeRepositoryInterface;
use League\OAuth2\Server\Repositories\UserRepositoryInterface;
use League\OAuth2\Server\RequestEvent;
use League\OAuth2\Server\RequestTypes\AuthorizationRequest;
use LogicException;
use Psr\Http\Message\ServerRequestInterface;
use TypeError;
/**
* Abstract grant class
* Abstract grant class.
*/
abstract class AbstractGrant implements GrantTypeInterface
{
/**
* Grant identifier
*
* @var string
*/
protected $identifier = '';
use EmitterAwareTrait, CryptTrait;
const SCOPE_DELIMITER_STRING = ' ';
const MAX_RANDOM_TOKEN_GENERATION_ATTEMPTS = 10;
/**
* Response type
*
* @var string
* @var ClientRepositoryInterface
*/
protected $responseType;
protected $clientRepository;
/**
* Callback to authenticate a user's name and password
*
* @var callable
* @var AccessTokenRepositoryInterface
*/
protected $callback;
protected $accessTokenRepository;
/**
* AuthServer instance
*
* @var \League\OAuth2\Server\AuthorizationServer
* @var ScopeRepositoryInterface
*/
protected $server;
protected $scopeRepository;
/**
* Access token expires in override
*
* @var int
* @var AuthCodeRepositoryInterface
*/
protected $accessTokenTTL;
protected $authCodeRepository;
/**
* {@inheritdoc}
* @var RefreshTokenRepositoryInterface
*/
public function getIdentifier()
protected $refreshTokenRepository;
/**
* @var UserRepositoryInterface
*/
protected $userRepository;
/**
* @var DateInterval
*/
protected $refreshTokenTTL;
/**
* @var CryptKey
*/
protected $privateKey;
/**
* @string
*/
protected $defaultScope;
/**
* @param ClientRepositoryInterface $clientRepository
*/
public function setClientRepository(ClientRepositoryInterface $clientRepository)
{
return $this->identifier;
$this->clientRepository = $clientRepository;
}
/**
* @param AccessTokenRepositoryInterface $accessTokenRepository
*/
public function setAccessTokenRepository(AccessTokenRepositoryInterface $accessTokenRepository)
{
$this->accessTokenRepository = $accessTokenRepository;
}
/**
* @param ScopeRepositoryInterface $scopeRepository
*/
public function setScopeRepository(ScopeRepositoryInterface $scopeRepository)
{
$this->scopeRepository = $scopeRepository;
}
/**
* @param RefreshTokenRepositoryInterface $refreshTokenRepository
*/
public function setRefreshTokenRepository(RefreshTokenRepositoryInterface $refreshTokenRepository)
{
$this->refreshTokenRepository = $refreshTokenRepository;
}
/**
* @param AuthCodeRepositoryInterface $authCodeRepository
*/
public function setAuthCodeRepository(AuthCodeRepositoryInterface $authCodeRepository)
{
$this->authCodeRepository = $authCodeRepository;
}
/**
* @param UserRepositoryInterface $userRepository
*/
public function setUserRepository(UserRepositoryInterface $userRepository)
{
$this->userRepository = $userRepository;
}
/**
* {@inheritdoc}
*/
public function setIdentifier($identifier)
public function setRefreshTokenTTL(DateInterval $refreshTokenTTL)
{
$this->identifier = $identifier;
return $this;
$this->refreshTokenTTL = $refreshTokenTTL;
}
/**
* {@inheritdoc}
*/
public function getResponseType()
{
return $this->responseType;
}
/**
* Get the TTL for an access token
* Set the private key
*
* @return int The TTL
* @param CryptKey $key
*/
public function getAccessTokenTTL()
public function setPrivateKey(CryptKey $key)
{
if ($this->accessTokenTTL) {
return $this->accessTokenTTL;
$this->privateKey = $key;
}
/**
* @param string $scope
*/
public function setDefaultScope($scope)
{
$this->defaultScope = $scope;
}
/**
* Validate the client.
*
* @param ServerRequestInterface $request
*
* @throws OAuthServerException
*
* @return ClientEntityInterface
*/
protected function validateClient(ServerRequestInterface $request)
{
list($clientId, $clientSecret) = $this->getClientCredentials($request);
if ($this->clientRepository->validateClient($clientId, $clientSecret, $this->getIdentifier()) === false) {
$this->getEmitter()->emit(new RequestEvent(RequestEvent::CLIENT_AUTHENTICATION_FAILED, $request));
throw OAuthServerException::invalidClient($request);
}
return $this->server->getAccessTokenTTL();
}
$client = $this->getClientEntityOrFail($clientId, $request);
/**
* Override the default access token expire time
*
* @param int $accessTokenTTL
*
* @return self
*/
public function setAccessTokenTTL($accessTokenTTL)
{
$this->accessTokenTTL = $accessTokenTTL;
// If a redirect URI is provided ensure it matches what is pre-registered
$redirectUri = $this->getRequestParameter('redirect_uri', $request, null);
return $this;
}
/**
* {@inheritdoc}
*/
public function setAuthorizationServer(AuthorizationServer $server)
{
$this->server = $server;
return $this;
}
/**
* Given a list of scopes, validate them and return an array of Scope entities
*
* @param string $scopeParam A string of scopes (e.g. "profile email birthday")
* @param \League\OAuth2\Server\Entity\ClientEntity $client Client entity
* @param string|null $redirectUri The redirect URI to return the user to
*
* @return \League\OAuth2\Server\Entity\ScopeEntity[]
*
* @throws \League\OAuth2\Server\Exception\InvalidScopeException If scope is invalid, or no scopes passed when required
* @throws
*/
public function validateScopes($scopeParam = '', ClientEntity $client, $redirectUri = null)
{
$scopesList = explode($this->server->getScopeDelimiter(), $scopeParam);
for ($i = 0; $i < count($scopesList); $i++) {
$scopesList[$i] = trim($scopesList[$i]);
if ($scopesList[$i] === '') {
unset($scopesList[$i]); // Remove any junk scopes
}
if ($redirectUri !== null) {
$this->validateRedirectUri($redirectUri, $client, $request);
}
if (
$this->server->scopeParamRequired() === true
&& $this->server->getDefaultScope() === null
&& count($scopesList) === 0
) {
throw new Exception\InvalidRequestException('scope');
} elseif (count($scopesList) === 0 && $this->server->getDefaultScope() !== null) {
if (is_array($this->server->getDefaultScope())) {
$scopesList = $this->server->getDefaultScope();
} else {
$scopesList = [0 => $this->server->getDefaultScope()];
}
}
$scopes = [];
foreach ($scopesList as $scopeItem) {
$scope = $this->server->getScopeStorage()->get(
$scopeItem,
$this->getIdentifier(),
$client->getId()
);
if (($scope instanceof ScopeEntity) === false) {
throw new Exception\InvalidScopeException($scopeItem, $redirectUri);
}
$scopes[$scope->getId()] = $scope;
}
return $scopes;
return $client;
}
/**
* Format the local scopes array
* Wrapper around ClientRepository::getClientEntity() that ensures we emit
* an event and throw an exception if the repo doesn't return a client
* entity.
*
* @param \League\OAuth2\Server\Entity\ScopeEntity[]
* This is a bit of defensive coding because the interface contract
* doesn't actually enforce non-null returns/exception-on-no-client so
* getClientEntity might return null. By contrast, this method will
* always either return a ClientEntityInterface or throw.
*
* @param string $clientId
* @param ServerRequestInterface $request
*
* @return ClientEntityInterface
*/
protected function getClientEntityOrFail($clientId, ServerRequestInterface $request)
{
$client = $this->clientRepository->getClientEntity($clientId);
if ($client instanceof ClientEntityInterface === false) {
$this->getEmitter()->emit(new RequestEvent(RequestEvent::CLIENT_AUTHENTICATION_FAILED, $request));
throw OAuthServerException::invalidClient($request);
}
return $client;
}
/**
* Gets the client credentials from the request from the request body or
* the Http Basic Authorization header
*
* @param ServerRequestInterface $request
*
* @return array
*/
protected function formatScopes($unformated = [])
protected function getClientCredentials(ServerRequestInterface $request)
{
$scopes = [];
foreach ($unformated as $scope) {
if ($scope instanceof ScopeEntity) {
$scopes[$scope->getId()] = $scope;
}
list($basicAuthUser, $basicAuthPassword) = $this->getBasicAuthCredentials($request);
$clientId = $this->getRequestParameter('client_id', $request, $basicAuthUser);
if (is_null($clientId)) {
throw OAuthServerException::invalidRequest('client_id');
}
return $scopes;
$clientSecret = $this->getRequestParameter('client_secret', $request, $basicAuthPassword);
return [$clientId, $clientSecret];
}
/**
* Validate redirectUri from the request.
* If a redirect URI is provided ensure it matches what is pre-registered
*
* @param string $redirectUri
* @param ClientEntityInterface $client
* @param ServerRequestInterface $request
*
* @throws OAuthServerException
*/
protected function validateRedirectUri(
string $redirectUri,
ClientEntityInterface $client,
ServerRequestInterface $request
) {
if (\is_string($client->getRedirectUri())
&& (strcmp($client->getRedirectUri(), $redirectUri) !== 0)
) {
$this->getEmitter()->emit(new RequestEvent(RequestEvent::CLIENT_AUTHENTICATION_FAILED, $request));
throw OAuthServerException::invalidClient($request);
} elseif (\is_array($client->getRedirectUri())
&& \in_array($redirectUri, $client->getRedirectUri(), true) === false
) {
$this->getEmitter()->emit(new RequestEvent(RequestEvent::CLIENT_AUTHENTICATION_FAILED, $request));
throw OAuthServerException::invalidClient($request);
}
}
/**
* Validate scopes in the request.
*
* @param string|array $scopes
* @param string $redirectUri
*
* @throws OAuthServerException
*
* @return ScopeEntityInterface[]
*/
public function validateScopes($scopes, $redirectUri = null)
{
if (!\is_array($scopes)) {
$scopes = $this->convertScopesQueryStringToArray($scopes);
}
$validScopes = [];
foreach ($scopes as $scopeItem) {
$scope = $this->scopeRepository->getScopeEntityByIdentifier($scopeItem);
if ($scope instanceof ScopeEntityInterface === false) {
throw OAuthServerException::invalidScope($scopeItem, $redirectUri);
}
$validScopes[] = $scope;
}
return $validScopes;
}
/**
* Converts a scopes query string to an array to easily iterate for validation.
*
* @param string $scopes
*
* @return array
*/
private function convertScopesQueryStringToArray($scopes)
{
return array_filter(explode(self::SCOPE_DELIMITER_STRING, trim($scopes)), function ($scope) {
return !empty($scope);
});
}
/**
* Retrieve request parameter.
*
* @param string $parameter
* @param ServerRequestInterface $request
* @param mixed $default
*
* @return null|string
*/
protected function getRequestParameter($parameter, ServerRequestInterface $request, $default = null)
{
$requestParameters = (array) $request->getParsedBody();
return $requestParameters[$parameter] ?? $default;
}
/**
* Retrieve HTTP Basic Auth credentials with the Authorization header
* of a request. First index of the returned array is the username,
* second is the password (so list() will work). If the header does
* not exist, or is otherwise an invalid HTTP Basic header, return
* [null, null].
*
* @param ServerRequestInterface $request
*
* @return string[]|null[]
*/
protected function getBasicAuthCredentials(ServerRequestInterface $request)
{
if (!$request->hasHeader('Authorization')) {
return [null, null];
}
$header = $request->getHeader('Authorization')[0];
if (strpos($header, 'Basic ') !== 0) {
return [null, null];
}
if (!($decoded = base64_decode(substr($header, 6)))) {
return [null, null];
}
if (strpos($decoded, ':') === false) {
return [null, null]; // HTTP Basic header without colon isn't valid
}
return explode(':', $decoded, 2);
}
/**
* Retrieve query string parameter.
*
* @param string $parameter
* @param ServerRequestInterface $request
* @param mixed $default
*
* @return null|string
*/
protected function getQueryStringParameter($parameter, ServerRequestInterface $request, $default = null)
{
return isset($request->getQueryParams()[$parameter]) ? $request->getQueryParams()[$parameter] : $default;
}
/**
* Retrieve cookie parameter.
*
* @param string $parameter
* @param ServerRequestInterface $request
* @param mixed $default
*
* @return null|string
*/
protected function getCookieParameter($parameter, ServerRequestInterface $request, $default = null)
{
return isset($request->getCookieParams()[$parameter]) ? $request->getCookieParams()[$parameter] : $default;
}
/**
* Retrieve server parameter.
*
* @param string $parameter
* @param ServerRequestInterface $request
* @param mixed $default
*
* @return null|string
*/
protected function getServerParameter($parameter, ServerRequestInterface $request, $default = null)
{
return isset($request->getServerParams()[$parameter]) ? $request->getServerParams()[$parameter] : $default;
}
/**
* Issue an access token.
*
* @param DateInterval $accessTokenTTL
* @param ClientEntityInterface $client
* @param string|null $userIdentifier
* @param ScopeEntityInterface[] $scopes
*
* @throws OAuthServerException
* @throws UniqueTokenIdentifierConstraintViolationException
*
* @return AccessTokenEntityInterface
*/
protected function issueAccessToken(
DateInterval $accessTokenTTL,
ClientEntityInterface $client,
$userIdentifier,
array $scopes = []
) {
$maxGenerationAttempts = self::MAX_RANDOM_TOKEN_GENERATION_ATTEMPTS;
$accessToken = $this->accessTokenRepository->getNewToken($client, $scopes, $userIdentifier);
$accessToken->setExpiryDateTime((new DateTimeImmutable())->add($accessTokenTTL));
$accessToken->setPrivateKey($this->privateKey);
while ($maxGenerationAttempts-- > 0) {
$accessToken->setIdentifier($this->generateUniqueIdentifier());
try {
$this->accessTokenRepository->persistNewAccessToken($accessToken);
return $accessToken;
} catch (UniqueTokenIdentifierConstraintViolationException $e) {
if ($maxGenerationAttempts === 0) {
throw $e;
}
}
}
}
/**
* Issue an auth code.
*
* @param DateInterval $authCodeTTL
* @param ClientEntityInterface $client
* @param string $userIdentifier
* @param string|null $redirectUri
* @param ScopeEntityInterface[] $scopes
*
* @throws OAuthServerException
* @throws UniqueTokenIdentifierConstraintViolationException
*
* @return AuthCodeEntityInterface
*/
protected function issueAuthCode(
DateInterval $authCodeTTL,
ClientEntityInterface $client,
$userIdentifier,
$redirectUri,
array $scopes = []
) {
$maxGenerationAttempts = self::MAX_RANDOM_TOKEN_GENERATION_ATTEMPTS;
$authCode = $this->authCodeRepository->getNewAuthCode();
$authCode->setExpiryDateTime((new DateTimeImmutable())->add($authCodeTTL));
$authCode->setClient($client);
$authCode->setUserIdentifier($userIdentifier);
if ($redirectUri !== null) {
$authCode->setRedirectUri($redirectUri);
}
foreach ($scopes as $scope) {
$authCode->addScope($scope);
}
while ($maxGenerationAttempts-- > 0) {
$authCode->setIdentifier($this->generateUniqueIdentifier());
try {
$this->authCodeRepository->persistNewAuthCode($authCode);
return $authCode;
} catch (UniqueTokenIdentifierConstraintViolationException $e) {
if ($maxGenerationAttempts === 0) {
throw $e;
}
}
}
}
/**
* @param AccessTokenEntityInterface $accessToken
*
* @throws OAuthServerException
* @throws UniqueTokenIdentifierConstraintViolationException
*
* @return RefreshTokenEntityInterface|null
*/
protected function issueRefreshToken(AccessTokenEntityInterface $accessToken)
{
$refreshToken = $this->refreshTokenRepository->getNewRefreshToken();
if ($refreshToken === null) {
return null;
}
$refreshToken->setExpiryDateTime((new DateTimeImmutable())->add($this->refreshTokenTTL));
$refreshToken->setAccessToken($accessToken);
$maxGenerationAttempts = self::MAX_RANDOM_TOKEN_GENERATION_ATTEMPTS;
while ($maxGenerationAttempts-- > 0) {
$refreshToken->setIdentifier($this->generateUniqueIdentifier());
try {
$this->refreshTokenRepository->persistNewRefreshToken($refreshToken);
return $refreshToken;
} catch (UniqueTokenIdentifierConstraintViolationException $e) {
if ($maxGenerationAttempts === 0) {
throw $e;
}
}
}
}
/**
* Generate a new unique identifier.
*
* @param int $length
*
* @throws OAuthServerException
*
* @return string
*/
protected function generateUniqueIdentifier($length = 40)
{
try {
return bin2hex(random_bytes($length));
// @codeCoverageIgnoreStart
} catch (TypeError $e) {
throw OAuthServerException::serverError('An unexpected error has occurred', $e);
} catch (Error $e) {
throw OAuthServerException::serverError('An unexpected error has occurred', $e);
} catch (Exception $e) {
// If you get this message, the CSPRNG failed hard.
throw OAuthServerException::serverError('Could not generate a random string', $e);
}
// @codeCoverageIgnoreEnd
}
/**
* {@inheritdoc}
*/
public function canRespondToAccessTokenRequest(ServerRequestInterface $request)
{
$requestParameters = (array) $request->getParsedBody();
return (
array_key_exists('grant_type', $requestParameters)
&& $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,303 +1,401 @@
<?php
/**
* OAuth 2.0 Auth code grant
*
* @package league/oauth2-server
* @author Alex Bilbie <hello@alexbilbie.com>
* @copyright Copyright (c) Alex Bilbie
* @license http://mit-license.org/
*
* @link https://github.com/thephpleague/oauth2-server
*/
namespace League\OAuth2\Server\Grant;
use League\OAuth2\Server\Entity\AccessTokenEntity;
use League\OAuth2\Server\Entity\AuthCodeEntity;
use League\OAuth2\Server\Entity\ClientEntity;
use League\OAuth2\Server\Entity\RefreshTokenEntity;
use League\OAuth2\Server\Entity\SessionEntity;
use League\OAuth2\Server\Event;
use League\OAuth2\Server\Exception;
use League\OAuth2\Server\Util\SecureKey;
use DateInterval;
use DateTimeImmutable;
use Exception;
use League\OAuth2\Server\CodeChallengeVerifiers\CodeChallengeVerifierInterface;
use League\OAuth2\Server\CodeChallengeVerifiers\PlainVerifier;
use League\OAuth2\Server\CodeChallengeVerifiers\S256Verifier;
use League\OAuth2\Server\Entities\ClientEntityInterface;
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\RequestEvent;
use League\OAuth2\Server\RequestTypes\AuthorizationRequest;
use League\OAuth2\Server\ResponseTypes\RedirectResponse;
use League\OAuth2\Server\ResponseTypes\ResponseTypeInterface;
use LogicException;
use Psr\Http\Message\ServerRequestInterface;
use stdClass;
/**
* Auth code grant class
*/
class AuthCodeGrant extends AbstractGrant
class AuthCodeGrant extends AbstractAuthorizeGrant
{
/**
* Grant identifier
*
* @var string
* @var DateInterval
*/
protected $identifier = 'authorization_code';
private $authCodeTTL;
/**
* Response type
*
* @var string
* @var bool
*/
protected $responseType = 'code';
private $requireCodeChallengeForPublicClients = true;
/**
* AuthServer instance
*
* @var \League\OAuth2\Server\AuthorizationServer
* @var CodeChallengeVerifierInterface[]
*/
protected $server = null;
private $codeChallengeVerifiers = [];
/**
* Access token expires in override
* @param AuthCodeRepositoryInterface $authCodeRepository
* @param RefreshTokenRepositoryInterface $refreshTokenRepository
* @param DateInterval $authCodeTTL
*
* @var int
* @throws Exception
*/
protected $accessTokenTTL = null;
public function __construct(
AuthCodeRepositoryInterface $authCodeRepository,
RefreshTokenRepositoryInterface $refreshTokenRepository,
DateInterval $authCodeTTL
) {
$this->setAuthCodeRepository($authCodeRepository);
$this->setRefreshTokenRepository($refreshTokenRepository);
$this->authCodeTTL = $authCodeTTL;
$this->refreshTokenTTL = new DateInterval('P1M');
/**
* The TTL of the auth token
*
* @var integer
*/
protected $authTokenTTL = 600;
/**
* Whether to require the client secret when
* completing the flow.
*
* @var boolean
*/
protected $requireClientSecret = true;
/**
* Override the default access token expire time
*
* @param int $authTokenTTL
*
* @return void
*/
public function setAuthTokenTTL($authTokenTTL)
{
$this->authTokenTTL = $authTokenTTL;
}
/**
*
* @param bool $required True to require client secret during access
* token request. False if not. Default = true
*/
public function setRequireClientSecret($required)
{
$this->requireClientSecret = $required;
}
/**
* True if client secret is required during
* access token request. False if it isn't.
*
* @return bool
*/
public function shouldRequireClientSecret()
{
return $this->requireClientSecret;
}
/**
* Check authorize parameters
*
* @return array Authorize request parameters
*
* @throws
*/
public function checkAuthorizeParams()
{
// Get required params
$clientId = $this->server->getRequest()->query->get('client_id', null);
if (is_null($clientId)) {
throw new Exception\InvalidRequestException('client_id');
if (in_array('sha256', hash_algos(), true)) {
$s256Verifier = new S256Verifier();
$this->codeChallengeVerifiers[$s256Verifier->getMethod()] = $s256Verifier;
}
$redirectUri = $this->server->getRequest()->query->get('redirect_uri', null);
if (is_null($redirectUri)) {
throw new Exception\InvalidRequestException('redirect_uri');
$plainVerifier = new PlainVerifier();
$this->codeChallengeVerifiers[$plainVerifier->getMethod()] = $plainVerifier;
}
/**
* Disable the requirement for a code challenge for public clients.
*/
public function disableRequireCodeChallengeForPublicClients()
{
$this->requireCodeChallengeForPublicClients = false;
}
/**
* Respond to an access token request.
*
* @param ServerRequestInterface $request
* @param ResponseTypeInterface $responseType
* @param DateInterval $accessTokenTTL
*
* @throws OAuthServerException
*
* @return ResponseTypeInterface
*/
public function respondToAccessTokenRequest(
ServerRequestInterface $request,
ResponseTypeInterface $responseType,
DateInterval $accessTokenTTL
) {
list($clientId) = $this->getClientCredentials($request);
$client = $this->getClientEntityOrFail($clientId, $request);
// Only validate the client if it is confidential
if ($client->isConfidential()) {
$this->validateClient($request);
}
// Validate client ID and redirect URI
$client = $this->server->getClientStorage()->get(
$clientId,
null,
$redirectUri,
$this->getIdentifier()
$encryptedAuthCode = $this->getRequestParameter('code', $request, null);
if ($encryptedAuthCode === null) {
throw OAuthServerException::invalidRequest('code');
}
try {
$authCodePayload = json_decode($this->decrypt($encryptedAuthCode));
$this->validateAuthorizationCode($authCodePayload, $client, $request);
$scopes = $this->scopeRepository->finalizeScopes(
$this->validateScopes($authCodePayload->scopes),
$this->getIdentifier(),
$client,
$authCodePayload->user_id
);
} catch (LogicException $e) {
throw OAuthServerException::invalidRequest('code', 'Cannot decrypt the authorization code', $e);
}
// Validate code challenge
if (!empty($authCodePayload->code_challenge)) {
$codeVerifier = $this->getRequestParameter('code_verifier', $request, null);
if ($codeVerifier === null) {
throw OAuthServerException::invalidRequest('code_verifier');
}
// Validate code_verifier according to RFC-7636
// @see: https://tools.ietf.org/html/rfc7636#section-4.1
if (preg_match('/^[A-Za-z0-9-._~]{43,128}$/', $codeVerifier) !== 1) {
throw OAuthServerException::invalidRequest(
'code_verifier',
'Code Verifier must follow the specifications of RFC-7636.'
);
}
if (property_exists($authCodePayload, 'code_challenge_method')) {
if (isset($this->codeChallengeVerifiers[$authCodePayload->code_challenge_method])) {
$codeChallengeVerifier = $this->codeChallengeVerifiers[$authCodePayload->code_challenge_method];
if ($codeChallengeVerifier->verifyCodeChallenge($codeVerifier, $authCodePayload->code_challenge) === false) {
throw OAuthServerException::invalidGrant('Failed to verify `code_verifier`.');
}
} else {
throw OAuthServerException::serverError(
sprintf(
'Unsupported code challenge method `%s`',
$authCodePayload->code_challenge_method
)
);
}
}
}
// Issue and persist new access token
$accessToken = $this->issueAccessToken($accessTokenTTL, $client, $authCodePayload->user_id, $scopes);
$this->getEmitter()->emit(new RequestEvent(RequestEvent::ACCESS_TOKEN_ISSUED, $request));
$responseType->setAccessToken($accessToken);
// Issue and persist new refresh token if given
$refreshToken = $this->issueRefreshToken($accessToken);
if ($refreshToken !== null) {
$this->getEmitter()->emit(new RequestEvent(RequestEvent::REFRESH_TOKEN_ISSUED, $request));
$responseType->setRefreshToken($refreshToken);
}
// Revoke used auth code
$this->authCodeRepository->revokeAuthCode($authCodePayload->auth_code_id);
return $responseType;
}
/**
* Validate the authorization code.
*
* @param stdClass $authCodePayload
* @param ClientEntityInterface $client
* @param ServerRequestInterface $request
*/
private function validateAuthorizationCode(
$authCodePayload,
ClientEntityInterface $client,
ServerRequestInterface $request
) {
if (time() > $authCodePayload->expire_time) {
throw OAuthServerException::invalidRequest('code', 'Authorization code has expired');
}
if ($this->authCodeRepository->isAuthCodeRevoked($authCodePayload->auth_code_id) === true) {
throw OAuthServerException::invalidRequest('code', 'Authorization code has been revoked');
}
if ($authCodePayload->client_id !== $client->getIdentifier()) {
throw OAuthServerException::invalidRequest('code', 'Authorization code was not issued to this client');
}
// 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');
}
}
/**
* Return the grant identifier that can be used in matching up requests.
*
* @return string
*/
public function getIdentifier()
{
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 (($client instanceof ClientEntity) === false) {
$this->server->getEventEmitter()->emit(new Event\ClientAuthenticationFailedEvent($this->server->getRequest()));
throw new Exception\InvalidClientException();
if ($clientId === null) {
throw OAuthServerException::invalidRequest('client_id');
}
$state = $this->server->getRequest()->query->get('state', null);
if ($this->server->stateParamRequired() === true && is_null($state)) {
throw new Exception\InvalidRequestException('state', $redirectUri);
$client = $this->getClientEntityOrFail($clientId, $request);
$redirectUri = $this->getQueryStringParameter('redirect_uri', $request);
if ($redirectUri !== null) {
$this->validateRedirectUri($redirectUri, $client, $request);
} elseif (empty($client->getRedirectUri()) ||
(\is_array($client->getRedirectUri()) && \count($client->getRedirectUri()) !== 1)) {
$this->getEmitter()->emit(new RequestEvent(RequestEvent::CLIENT_AUTHENTICATION_FAILED, $request));
throw OAuthServerException::invalidClient($request);
} else {
$redirectUri = \is_array($client->getRedirectUri())
? $client->getRedirectUri()[0]
: $client->getRedirectUri();
}
$responseType = $this->server->getRequest()->query->get('response_type', null);
if (is_null($responseType)) {
throw new Exception\InvalidRequestException('response_type', $redirectUri);
}
// Ensure response type is one that is recognised
if (!in_array($responseType, $this->server->getResponseTypes())) {
throw new Exception\UnsupportedResponseTypeException($responseType, $redirectUri);
}
// Validate any scopes that are in the request
$scopeParam = $this->server->getRequest()->query->get('scope', '');
$scopes = $this->validateScopes($scopeParam, $client, $redirectUri);
return [
'client' => $client,
'redirect_uri' => $redirectUri,
'state' => $state,
'response_type' => $responseType,
'scopes' => $scopes
];
}
/**
* Parse a new authorize request
*
* @param string $type The session owner's type
* @param string $typeId The session owner's ID
* @param array $authParams The authorize request $_GET parameters
*
* @return string An authorisation code
*/
public function newAuthorizeRequest($type, $typeId, $authParams = [])
{
// Create a new session
$session = new SessionEntity($this->server);
$session->setOwner($type, $typeId);
$session->associateClient($authParams['client']);
// Create a new auth code
$authCode = new AuthCodeEntity($this->server);
$authCode->setId(SecureKey::generate());
$authCode->setRedirectUri($authParams['redirect_uri']);
$authCode->setExpireTime(time() + $this->authTokenTTL);
foreach ($authParams['scopes'] as $scope) {
$authCode->associateScope($scope);
$session->associateScope($scope);
}
$session->save();
$authCode->setSession($session);
$authCode->save();
return $authCode->generateRedirectUri($authParams['state']);
}
/**
* Complete the auth code grant
*
* @return array
*
* @throws
*/
public function completeFlow()
{
// Get the required params
$clientId = $this->server->getRequest()->request->get('client_id', $this->server->getRequest()->getUser());
if (is_null($clientId)) {
throw new Exception\InvalidRequestException('client_id');
}
$clientSecret = $this->server->getRequest()->request->get('client_secret',
$this->server->getRequest()->getPassword());
if ($this->shouldRequireClientSecret() && is_null($clientSecret)) {
throw new Exception\InvalidRequestException('client_secret');
}
$redirectUri = $this->server->getRequest()->request->get('redirect_uri', null);
if (is_null($redirectUri)) {
throw new Exception\InvalidRequestException('redirect_uri');
}
// Validate client ID and client secret
$client = $this->server->getClientStorage()->get(
$clientId,
$clientSecret,
$redirectUri,
$this->getIdentifier()
$scopes = $this->validateScopes(
$this->getQueryStringParameter('scope', $request, $this->defaultScope),
$redirectUri
);
if (($client instanceof ClientEntity) === false) {
$this->server->getEventEmitter()->emit(new Event\ClientAuthenticationFailedEvent($this->server->getRequest()));
throw new Exception\InvalidClientException();
$stateParameter = $this->getQueryStringParameter('state', $request);
$authorizationRequest = new AuthorizationRequest();
$authorizationRequest->setGrantTypeId($this->getIdentifier());
$authorizationRequest->setClient($client);
$authorizationRequest->setRedirectUri($redirectUri);
if ($stateParameter !== null) {
$authorizationRequest->setState($stateParameter);
}
// Validate the auth code
$authCode = $this->server->getRequest()->request->get('code', null);
if (is_null($authCode)) {
throw new Exception\InvalidRequestException('code');
$authorizationRequest->setScopes($scopes);
$codeChallenge = $this->getQueryStringParameter('code_challenge', $request);
if ($codeChallenge !== null) {
$codeChallengeMethod = $this->getQueryStringParameter('code_challenge_method', $request, 'plain');
if (array_key_exists($codeChallengeMethod, $this->codeChallengeVerifiers) === false) {
throw OAuthServerException::invalidRequest(
'code_challenge_method',
'Code challenge method must be one of ' . implode(', ', array_map(
function ($method) {
return '`' . $method . '`';
},
array_keys($this->codeChallengeVerifiers)
))
);
}
// Validate code_challenge according to RFC-7636
// @see: https://tools.ietf.org/html/rfc7636#section-4.2
if (preg_match('/^[A-Za-z0-9-._~]{43,128}$/', $codeChallenge) !== 1) {
throw OAuthServerException::invalidRequest(
'code_challenged',
'Code challenge must follow the specifications of RFC-7636.'
);
}
$authorizationRequest->setCodeChallenge($codeChallenge);
$authorizationRequest->setCodeChallengeMethod($codeChallengeMethod);
} elseif ($this->requireCodeChallengeForPublicClients && !$client->isConfidential()) {
throw OAuthServerException::invalidRequest('code_challenge', 'Code challenge must be provided for public clients');
}
$code = $this->server->getAuthCodeStorage()->get($authCode);
if (($code instanceof AuthCodeEntity) === false) {
throw new Exception\InvalidRequestException('code');
}
// Ensure the auth code hasn't expired
if ($code->isExpired() === true) {
throw new Exception\InvalidRequestException('code');
}
// Check redirect URI presented matches redirect URI originally used in authorize request
if ($code->getRedirectUri() !== $redirectUri) {
throw new Exception\InvalidRequestException('redirect_uri');
}
$session = $code->getSession();
$session->associateClient($client);
$authCodeScopes = $code->getScopes();
// Generate the access token
$accessToken = new AccessTokenEntity($this->server);
$accessToken->setId(SecureKey::generate());
$accessToken->setExpireTime($this->getAccessTokenTTL() + time());
foreach ($authCodeScopes as $authCodeScope) {
$session->associateScope($authCodeScope);
}
foreach ($session->getScopes() as $scope) {
$accessToken->associateScope($scope);
}
$this->server->getTokenType()->setSession($session);
$this->server->getTokenType()->setParam('access_token', $accessToken->getId());
$this->server->getTokenType()->setParam('expires_in', $this->getAccessTokenTTL());
// Associate a refresh token if set
if ($this->server->hasGrantType('refresh_token')) {
$refreshToken = new RefreshTokenEntity($this->server);
$refreshToken->setId(SecureKey::generate());
$refreshToken->setExpireTime($this->server->getGrantType('refresh_token')->getRefreshTokenTTL() + time());
$this->server->getTokenType()->setParam('refresh_token', $refreshToken->getId());
}
// Expire the auth code
$code->expire();
// Save all the things
$accessToken->setSession($session);
$accessToken->save();
if (isset($refreshToken) && $this->server->hasGrantType('refresh_token')) {
$refreshToken->setAccessToken($accessToken);
$refreshToken->save();
}
return $this->server->getTokenType()->generateResponse();
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()
?? $this->getClientRedirectUri($authorizationRequest);
// 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()
);
$payload = [
'client_id' => $authCode->getClient()->getIdentifier(),
'redirect_uri' => $authCode->getRedirectUri(),
'auth_code_id' => $authCode->getIdentifier(),
'scopes' => $authCode->getScopes(),
'user_id' => $authCode->getUserIdentifier(),
'expire_time' => (new DateTimeImmutable())->add($this->authCodeTTL)->getTimestamp(),
'code_challenge' => $authorizationRequest->getCodeChallenge(),
'code_challenge_method' => $authorizationRequest->getCodeChallengeMethod(),
];
$jsonPayload = json_encode($payload);
if ($jsonPayload === false) {
throw new LogicException('An error was encountered when JSON encoding the authorization request response');
}
$response = new RedirectResponse();
$response->setRedirectUri(
$this->makeRedirectUri(
$finalRedirectUri,
[
'code' => $this->encrypt($jsonPayload),
'state' => $authorizationRequest->getState(),
]
)
);
return $response;
}
// The user denied the client, redirect them back with an error
throw OAuthServerException::accessDenied(
'The user denied the request',
$this->makeRedirectUri(
$finalRedirectUri,
[
'state' => $authorizationRequest->getState(),
]
)
);
}
/**
* Get the client redirect URI if not set in the request.
*
* @param AuthorizationRequest $authorizationRequest
*
* @return string
*/
private function getClientRedirectUri(AuthorizationRequest $authorizationRequest)
{
return \is_array($authorizationRequest->getClient()->getRedirectUri())
? $authorizationRequest->getClient()->getRedirectUri()[0]
: $authorizationRequest->getClient()->getRedirectUri();
}
}

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