mirror of
https://github.com/elyby/oauth2-server.git
synced 2025-05-31 14:12:07 +05:30
Compare commits
273 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
f78dc2eca0 | ||
|
105b3116dc | ||
|
01677a564e | ||
|
4c4b0633b1 | ||
|
c4a75b2880 | ||
|
e091d48127 | ||
|
a798cfdc5d | ||
|
56e8d374fb | ||
|
b1bfff7325 | ||
|
32cde01ab2 | ||
|
11ccc305d0 | ||
|
d7df2f7e24 | ||
|
b8b92e5925 | ||
|
0ebdcd2ab8 | ||
|
9dee08ba3d | ||
|
065ef5db99 | ||
|
039537ebe2 | ||
|
d8930af5ee | ||
|
ada8d20be6 | ||
|
090c01d3d1 | ||
|
4b6ba5859c | ||
|
57323f38f7 | ||
|
46cd448a47 | ||
|
c874c59b9c | ||
|
c3a4670c11 | ||
|
17b6e2a207 | ||
|
54422a244f | ||
|
9899aa1f99 | ||
|
32efd091a1 | ||
|
68e4b1d390 | ||
|
5ee1583c5b | ||
|
66de05a395 | ||
|
df20da1235 | ||
|
7321622104 | ||
|
84187041bd | ||
|
9eccc40eb6 | ||
|
8b865cc523 | ||
|
9775c0076b | ||
|
b68ef973df | ||
|
c6e5f12a7c | ||
|
6b88cbeb13 | ||
|
64a0fcb3a6 | ||
|
78dbb267ed | ||
|
22e6a350dd | ||
|
c0936cc320 | ||
|
bb82651bec | ||
|
599c9aba75 | ||
|
4c6c189dff | ||
|
8e8aed1a50 | ||
|
4a4f4fe2d7 | ||
|
6b18a9441a | ||
|
44ff7b33a1 | ||
|
db055f790d | ||
|
d1bc4848c8 | ||
|
cf63403585 | ||
|
cdf43e498e | ||
|
a12fc98b0d | ||
|
019d285235 | ||
|
0bb968f413 | ||
|
88b19ad2d0 | ||
|
6856699cab | ||
|
72cd9a62e1 | ||
|
acf262f879 | ||
|
5241309bdb | ||
|
9a93dca05c | ||
|
a6b7a5cedc | ||
|
78b6bddc4d | ||
|
14b6761c0f | ||
|
7c61922f07 | ||
|
20535ad95b | ||
|
e885114714 | ||
|
f80d0d39a4 | ||
|
7bfd5b7d0d | ||
|
143a2e32f7 | ||
|
8f418cff08 | ||
|
fcec1f3442 | ||
|
46e7eef14e | ||
|
51f44fdf17 | ||
|
f8b2e80ef3 | ||
|
7045785d89 | ||
|
301ddc53c7 | ||
|
2a6f900323 | ||
|
fb8f47e868 | ||
|
5b192b3548 | ||
|
bf55ce1f73 | ||
|
4942585f4f | ||
|
1575128162 | ||
|
78c2067698 | ||
|
f765f134c9 | ||
|
257318e524 | ||
|
77737e7894 | ||
|
f007e25070 | ||
|
25c2e9b31b | ||
|
6ed9cbf701 | ||
|
7c35778316 | ||
|
f6f39698d9 | ||
|
3904767873 | ||
|
c3a7c418da | ||
|
af5a06098b | ||
|
6205611a71 | ||
|
9f3648039b | ||
|
08c356a1e1 | ||
|
70e32ce9bf | ||
|
94a1c18fa9 | ||
|
88b01b792a | ||
|
0178a837d4 | ||
|
2025bd6a30 | ||
|
e7f18911f3 | ||
|
8e8ac35dcb | ||
|
16ed4ea51c | ||
|
de635f826f | ||
|
3e8577f889 | ||
|
525b9b3d3e | ||
|
f7413c2f15 | ||
|
6e583fdf8a | ||
|
f9bde23799 | ||
|
2328f59601 | ||
|
103b0cc50d | ||
|
eb7526ae97 | ||
|
03e8eb6157 | ||
|
7b803365f9 | ||
|
204706f1ff | ||
|
4c6dab3f55 | ||
|
54bedda11b | ||
|
883ba8b573 | ||
|
0d1e61422a | ||
|
a722659200 | ||
|
a80310b01c | ||
|
c017b59342 | ||
|
920c0c296a | ||
|
b0db04461f | ||
|
495b55d1e8 | ||
|
92a483b3bd | ||
|
6083870603 | ||
|
6359535e32 | ||
|
5969082963 | ||
|
7a6d9a4510 | ||
|
7c86d3b848 | ||
|
d3a7b442ce | ||
|
ba30e34511 | ||
|
e24dff2723 | ||
|
625876f7ae | ||
|
4f2dfc20b9 | ||
|
1512960d92 | ||
|
273ea0ba68 | ||
|
096a4a2883 | ||
|
a68f07f734 | ||
|
a0c4900ee7 | ||
|
4c0c10ae98 | ||
|
0fb0100088 | ||
|
8f50e58ba9 | ||
|
8225b4e697 | ||
|
236a3a0358 | ||
|
b00a4e169e | ||
|
c034c3b13c | ||
|
287c371586 | ||
|
634578997f | ||
|
b8c5056c31 | ||
|
79aa1988d8 | ||
|
7c35985c1e | ||
|
c75d0e0f0e | ||
|
5d3516c7b4 | ||
|
d4fb00628e | ||
|
4bc835c007 | ||
|
fdb1d70874 | ||
|
6f71a2d178 | ||
|
651709b70f | ||
|
3f6e91575d | ||
|
8f5e0ce9f7 | ||
|
5410a42bb6 | ||
|
b7064befe4 | ||
|
44937f3600 | ||
|
76ea6b5a6c | ||
|
4689802c30 | ||
|
6ee71754c4 | ||
|
b3329dbeac | ||
|
0ca2511d1e | ||
|
2c2ef800d4 | ||
|
d8d49f742e | ||
|
e758121458 | ||
|
47656cd9b5 | ||
|
b59106dc64 | ||
|
c6faa228fe | ||
|
4eee48ca4e | ||
|
00518dded7 | ||
|
3615cbeedf | ||
|
6773db66c6 | ||
|
5ca2152313 | ||
|
5cba35456f | ||
|
be9bd76f35 | ||
|
3c0a7f14ab | ||
|
198f4c4b6f | ||
|
6f0a0cca4e | ||
|
5430ddb230 | ||
|
1ccfd9be32 | ||
|
a83c56f570 | ||
|
d7dd07cf18 | ||
|
0fed56a265 | ||
|
fc9e912e06 | ||
|
39281a6f38 | ||
|
656a8d7a56 | ||
|
6c942f25f4 | ||
|
8274c56fc2 | ||
|
de8f6ff539 | ||
|
8f69f4f9a9 | ||
|
4d2ccac8ed | ||
|
a38b7f97f9 | ||
|
197657f2b9 | ||
|
e513b42117 | ||
|
b1ce1f872b | ||
|
1de13cf892 | ||
|
d8e1e0e00e | ||
|
1ad44d1ce0 | ||
|
b480373249 | ||
|
3ad97b4ef4 | ||
|
0490736861 | ||
|
abaf399f5f | ||
|
55c8df8312 | ||
|
c5db707e69 | ||
|
ed7f78179a | ||
|
6e92239dd7 | ||
|
f5d731def9 | ||
|
03815cec6d | ||
|
c71dc47459 | ||
|
3bcd8fc3f8 | ||
|
db6d4e0dc6 | ||
|
f19189a999 | ||
|
ec9c91cc11 | ||
|
c3457107ee | ||
|
a9f61fd3ed | ||
|
b78d8ca1d8 | ||
|
8f82e8ef86 | ||
|
d88e01c7dd | ||
|
d21374fb0b | ||
|
31e5f4d33c | ||
|
a773405adf | ||
|
ccc845b195 | ||
|
21cd917892 | ||
|
a2c418ee07 | ||
|
b220368583 | ||
|
2d26c38d6c | ||
|
eeaa68400f | ||
|
56c73d2427 | ||
|
f632fcc997 | ||
|
618d84ddcf | ||
|
ace42e89e0 | ||
|
c496df98e4 | ||
|
2496653968 | ||
|
abf66ef9c8 | ||
|
4b9ec488f4 | ||
|
726d879607 | ||
|
b256195421 | ||
|
c84ea1ea62 | ||
|
16685ccde4 | ||
|
7934c7bb53 | ||
|
c174b6fc65 | ||
|
75ced70248 | ||
|
5b7fdaeece | ||
|
430a752315 | ||
|
810544ec0a | ||
|
34a6b66b8c | ||
|
61738a7fe2 | ||
|
51184259d1 | ||
|
b21de11429 | ||
|
cf6e86c9d4 | ||
|
f6fdbc7142 | ||
|
7f7f45662a | ||
|
f92a68cc72 | ||
|
295d8ffa24 | ||
|
3d08140651 | ||
|
ec8a8393ee | ||
|
3869b8f406 | ||
|
d43391564c |
@@ -2,7 +2,6 @@ filter:
|
||||
excluded_paths:
|
||||
- tests/*
|
||||
- vendor/*
|
||||
- examples/*
|
||||
checks:
|
||||
php:
|
||||
code_rating: true
|
||||
@@ -21,8 +20,7 @@ checks:
|
||||
fix_doc_comments: true
|
||||
tools:
|
||||
external_code_coverage:
|
||||
timeout: 600
|
||||
runs: 3
|
||||
timeout: 1800
|
||||
php_code_coverage: false
|
||||
php_code_sniffer:
|
||||
config:
|
||||
@@ -34,4 +32,4 @@ tools:
|
||||
excluded_dirs: [vendor, tests, examples]
|
||||
php_cpd:
|
||||
enabled: true
|
||||
excluded_dirs: [vendor, tests, examples]
|
||||
excluded_dirs: [vendor, tests, examples]
|
||||
|
@@ -7,6 +7,7 @@ cache:
|
||||
- vendor
|
||||
|
||||
php:
|
||||
- 5.5.9
|
||||
- 5.5
|
||||
- 5.6
|
||||
- 7.0
|
||||
@@ -20,5 +21,4 @@ script:
|
||||
|
||||
branches:
|
||||
only:
|
||||
- master
|
||||
- V5-WIP
|
||||
- master
|
99
CHANGELOG.md
99
CHANGELOG.md
@@ -1,5 +1,104 @@
|
||||
# Changelog
|
||||
|
||||
## 5.1.3 (released 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 (released 2016-09-19)
|
||||
|
||||
* Fixed `finalizeScopes` call (Issue #650)
|
||||
|
||||
## 5.1.1 (released 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 (released 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 (released 2016-05-04)
|
||||
|
||||
* Fix hints in PasswordGrant (Issue #560)
|
||||
* Add meaning of `Resource owner` to terminology.md (Issue #561)
|
||||
* Use constant for event name instead of explicit string (Issue #563)
|
||||
* Remove unused request property (Issue #564)
|
||||
* Correct wrong phpdoc (Issue #569)
|
||||
* Fixed typo in exception string (Issue #570)
|
||||
|
||||
## 5.0.2 (released 2016-04-18)
|
||||
|
||||
* `state` parameter is now correctly returned after implicit grant authorization
|
||||
* Small code and docblock improvements
|
||||
|
||||
## 5.0.1 (released 2016-04-18)
|
||||
|
||||
* Fixes an issue (#550) whereby it was unclear whether or not to validate a client's secret during a request.
|
||||
|
||||
## 5.0.0 (released 2016-04-17)
|
||||
|
||||
Version 5 is a complete code rewrite.
|
||||
|
||||
* JWT support
|
||||
* PSR-7 support
|
||||
* Improved exception errors
|
||||
* Replace all occurrences of the term "Storage" with "Repository"
|
||||
* Simplify repositories
|
||||
* Entities conform to interfaces and use traits
|
||||
* Auth code grant updated
|
||||
* Allow support for public clients
|
||||
* Add support for #439
|
||||
* Client credentials grant updated
|
||||
* Password grant updated
|
||||
* Allow support for public clients
|
||||
* Refresh token grant updated
|
||||
* Implement Implicit grant
|
||||
* Bearer token output type
|
||||
* Remove MAC token output type
|
||||
* Authorization server rewrite
|
||||
* Resource server class moved to PSR-7 middleware
|
||||
* Tests
|
||||
* Much much better documentation
|
||||
|
||||
Changes since RC2:
|
||||
|
||||
* Renamed Server class to AuthorizationServer
|
||||
* Added ResourceServer class
|
||||
* Run unit tests again PHP 5.5.9 as it's the minimum supported version
|
||||
* Enable PHPUnit 5.0 support
|
||||
* Improved examples and documentation
|
||||
* Make it clearer that the implicit grant doesn't support refresh tokens
|
||||
* Improved refresh token validation errors
|
||||
* Fixed refresh token expiry date
|
||||
|
||||
## 5.0.0-RC2 (released 2016-04-10)
|
||||
|
||||
Changes since RC1:
|
||||
|
||||
* Allow multiple client redirect URIs (Issue #511)
|
||||
* Remove unused mac token interface (Issue #503)
|
||||
* Handle RSA key passphrase (Issue #502)
|
||||
* Remove access token repository from response types (Issue #501)
|
||||
* Remove unnecessary methods from entity interfaces (Issue #490)
|
||||
* Ensure incoming JWT hasn't expired (Issue #509)
|
||||
* Fix client identifier passed where user identifier is expected (Issue #498)
|
||||
* Removed built-in entities; added traits to for quick re-use (Issue #504)
|
||||
* Redirect uri is required only if the "redirect_uri" parameter was included in the authorization request (Issue #514)
|
||||
* Removed templating for auth code and implicit grants (Issue #499)
|
||||
|
||||
## 5.0.0-RC1 (release 2016-03-24)
|
||||
|
||||
Version 5 is a complete code rewrite.
|
||||
|
26
README.md
26
README.md
@@ -1,4 +1,4 @@
|
||||
# PHP OAuth 2.0 Server by [@alexbilbie](https://twitter.com/alexbilbie)
|
||||
# PHP OAuth 2.0 Server
|
||||
|
||||
[](https://github.com/thephpleague/oauth2-server/releases)
|
||||
[](LICENSE.md)
|
||||
@@ -17,14 +17,14 @@ It supports out of the box the following grants:
|
||||
* Resource owner password credentials grant
|
||||
* Refresh grant
|
||||
|
||||
You can also easily define your own grants.
|
||||
The following RFCs are implemented:
|
||||
|
||||
In addition it supports the following token response types:
|
||||
* [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)
|
||||
|
||||
* Bearer (JWT) tokens
|
||||
* MAC tokens
|
||||
|
||||
You can also create you own tokens.
|
||||
This library was created by Alex Bilbie. Find him on Twitter at [@alexbilbie](https://twitter.com/alexbilbie).
|
||||
|
||||
## Requirements
|
||||
|
||||
@@ -35,10 +35,12 @@ The following versions of PHP are supported:
|
||||
* PHP 7.0
|
||||
* HHVM
|
||||
|
||||
The `openssl` extension is also required.
|
||||
|
||||
## Documentation
|
||||
|
||||
The library documentation can be found at [http://oauth2.thephpleague.com](http://oauth2.thephpleague.com).
|
||||
You can contribute to this documentation in the [gh-pages branch](https://github.com/thephpleague/oauth2-server/tree/gh-pages/).
|
||||
The library documentation can be found at [https://oauth2.thephpleague.com](https://oauth2.thephpleague.com).
|
||||
You can contribute to the documentation in the [gh-pages branch](https://github.com/thephpleague/oauth2-server/tree/gh-pages/).
|
||||
|
||||
## Changelog
|
||||
|
||||
@@ -54,9 +56,13 @@ Bugs and feature request are tracked on [GitHub](https://github.com/thephpleague
|
||||
|
||||
If you have any questions about OAuth _please_ open a ticket here; please **don't** email the address below.
|
||||
|
||||
## Commercial Support
|
||||
|
||||
If you would like help implementing this library into your existing platform, or would be interested in OAuth advice or training for you and your team please get in touch with [Glynde Labs](https://glyndelabs.com).
|
||||
|
||||
## Security
|
||||
|
||||
If you discover any security related issues, please email hello@alexbilbie.com instead of using the issue tracker.
|
||||
If you discover any security related issues, please email `hello@alexbilbie.com` instead of using the issue tracker.
|
||||
|
||||
## License
|
||||
|
||||
|
@@ -1,19 +1,20 @@
|
||||
{
|
||||
"name": "league/oauth2-server",
|
||||
"description": "A lightweight and powerful OAuth 2.0 authorization and resource server library with support for all the core specification grants. This library will allow you to secure your API with OAuth and allow your applications users to approve apps that want to access their data from your API.",
|
||||
"homepage": "http://oauth2.thephpleague.com/",
|
||||
"homepage": "https://oauth2.thephpleague.com/",
|
||||
"license": "MIT",
|
||||
"require": {
|
||||
"php": ">=5.5.9",
|
||||
"ext-openssl": "*",
|
||||
"league/event": "^2.1",
|
||||
"lcobucci/jwt": "^3.1",
|
||||
"paragonie/random_compat": "^1.1",
|
||||
"paragonie/random_compat": "^1.1 || ^2.0",
|
||||
"psr/http-message": "^1.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "^4.8",
|
||||
"league/plates": "^3.1",
|
||||
"zendframework/zend-diactoros": "^1.0"
|
||||
"phpunit/phpunit": "^4.8 || ^5.0",
|
||||
"zendframework/zend-diactoros": "^1.0",
|
||||
"indigophp/hash-compat": "^1.1"
|
||||
},
|
||||
"repositories": [
|
||||
{
|
||||
@@ -65,9 +66,6 @@
|
||||
}
|
||||
},
|
||||
"suggest": {
|
||||
"league/plates": "Used for parsing authorization code templates",
|
||||
"twig/twig": "Used for parsing authorization code templates",
|
||||
"smarty/smarty": "Used for parsing authorization code templates",
|
||||
"mustache/mustache": "Used for parsing authorization code templates"
|
||||
"indigophp/hash-compat": "Polyfill for hash_equals function for PHP 5.5"
|
||||
}
|
||||
}
|
||||
|
@@ -2,8 +2,8 @@
|
||||
|
||||
## Installation
|
||||
|
||||
0. Run `composer install --no-dev` in this directory to install dependencies
|
||||
0. Create a private key `openssl genrsa -out private.key 1024`
|
||||
0. 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`
|
||||
|
@@ -1,18 +1,17 @@
|
||||
{
|
||||
"repositories": [
|
||||
{
|
||||
"type": "path",
|
||||
"url": ".."
|
||||
}
|
||||
],
|
||||
"require": {
|
||||
"slim/slim": "3.0.*",
|
||||
"league/oauth2-server": "dev-V5-WIP",
|
||||
"league/plates": "^3.1"
|
||||
"slim/slim": "3.0.*"
|
||||
},
|
||||
"require-dev": {
|
||||
"league/event": "^2.1",
|
||||
"lcobucci/jwt": "^3.1",
|
||||
"paragonie/random_compat": "^1.1",
|
||||
"psr/http-message": "^1.0"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"OAuth2ServerExamples\\": "src/"
|
||||
"OAuth2ServerExamples\\": "src/",
|
||||
"League\\OAuth2\\Server\\": "../src/"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
452
examples/composer.lock
generated
452
examples/composer.lock
generated
@@ -4,8 +4,8 @@
|
||||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
|
||||
"This file is @generated automatically"
|
||||
],
|
||||
"hash": "143453cc35e7f499b130b6460222dc5a",
|
||||
"content-hash": "1ea46581fb6db25f323a37a45ef74f95",
|
||||
"hash": "48bcb7a3514d7c7f271c554ba1440124",
|
||||
"content-hash": "e41be75973527cb9d63f27ad14ac8624",
|
||||
"packages": [
|
||||
{
|
||||
"name": "container-interop/container-interop",
|
||||
@@ -34,243 +34,6 @@
|
||||
"description": "Promoting the interoperability of container objects (DIC, SL, etc.)",
|
||||
"time": "2014-12-30 15:22:37"
|
||||
},
|
||||
{
|
||||
"name": "lcobucci/jwt",
|
||||
"version": "3.1.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/lcobucci/jwt.git",
|
||||
"reference": "31499db4e692b343cec7ff345932899f98fde1cf"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/lcobucci/jwt/zipball/31499db4e692b343cec7ff345932899f98fde1cf",
|
||||
"reference": "31499db4e692b343cec7ff345932899f98fde1cf",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"ext-openssl": "*",
|
||||
"php": ">=5.5"
|
||||
},
|
||||
"require-dev": {
|
||||
"mdanter/ecc": "~0.3",
|
||||
"mikey179/vfsstream": "~1.5",
|
||||
"phpmd/phpmd": "~2.2",
|
||||
"phpunit/php-invoker": "~1.1",
|
||||
"phpunit/phpunit": "~4.5",
|
||||
"squizlabs/php_codesniffer": "~2.3"
|
||||
},
|
||||
"suggest": {
|
||||
"mdanter/ecc": "Required to use Elliptic Curves based algorithms."
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "3.1-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Lcobucci\\JWT\\": "src"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"BSD-3-Clause"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Luís Otávio Cobucci Oblonczyk",
|
||||
"email": "lcobucci@gmail.com",
|
||||
"role": "Developer"
|
||||
}
|
||||
],
|
||||
"description": "A simple library to work with JSON Web Token and JSON Web Signature",
|
||||
"keywords": [
|
||||
"JWS",
|
||||
"jwt"
|
||||
],
|
||||
"time": "2015-11-15 01:42:47"
|
||||
},
|
||||
{
|
||||
"name": "league/event",
|
||||
"version": "2.1.2",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/thephpleague/event.git",
|
||||
"reference": "e4bfc88dbcb60c8d8a2939a71f9813e141bbe4cd"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/thephpleague/event/zipball/e4bfc88dbcb60c8d8a2939a71f9813e141bbe4cd",
|
||||
"reference": "e4bfc88dbcb60c8d8a2939a71f9813e141bbe4cd",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=5.4.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"henrikbjorn/phpspec-code-coverage": "~1.0.1",
|
||||
"phpspec/phpspec": "~2.0.0"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "2.2-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"League\\Event\\": "src/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Frank de Jonge",
|
||||
"email": "info@frenky.net"
|
||||
}
|
||||
],
|
||||
"description": "Event package",
|
||||
"keywords": [
|
||||
"emitter",
|
||||
"event",
|
||||
"listener"
|
||||
],
|
||||
"time": "2015-05-21 12:24:47"
|
||||
},
|
||||
{
|
||||
"name": "league/oauth2-server",
|
||||
"version": "dev-V5-WIP",
|
||||
"dist": {
|
||||
"type": "path",
|
||||
"url": "../",
|
||||
"reference": "0fbe109e2004c71feac2bd14fd85aff97704b2e5",
|
||||
"shasum": null
|
||||
},
|
||||
"require": {
|
||||
"lcobucci/jwt": "^3.1",
|
||||
"league/event": "^2.1",
|
||||
"paragonie/random_compat": "^1.1",
|
||||
"php": ">=5.5.9",
|
||||
"psr/http-message": "^1.0"
|
||||
},
|
||||
"replace": {
|
||||
"league/oauth2server": "*",
|
||||
"lncd/oauth2": "*"
|
||||
},
|
||||
"require-dev": {
|
||||
"league/plates": "^3.1",
|
||||
"phpunit/phpunit": "^4.8",
|
||||
"zendframework/zend-diactoros": "^1.0"
|
||||
},
|
||||
"suggest": {
|
||||
"league/plates": "Used for parsing authorization code templates",
|
||||
"mustache/mustache": "Used for parsing authorization code templates",
|
||||
"smarty/smarty": "Used for parsing authorization code templates",
|
||||
"twig/twig": "Used for parsing authorization code templates"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-V5-WIP": "5.0-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"League\\OAuth2\\Server\\": "src/"
|
||||
}
|
||||
},
|
||||
"autoload-dev": {
|
||||
"psr-4": {
|
||||
"LeagueTests\\": "tests/"
|
||||
}
|
||||
},
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Alex Bilbie",
|
||||
"email": "hello@alexbilbie.com",
|
||||
"homepage": "http://www.alexbilbie.com",
|
||||
"role": "Developer"
|
||||
}
|
||||
],
|
||||
"description": "A lightweight and powerful OAuth 2.0 authorization and resource server library with support for all the core specification grants. This library will allow you to secure your API with OAuth and allow your applications users to approve apps that want to access their data from your API.",
|
||||
"homepage": "http://oauth2.thephpleague.com/",
|
||||
"keywords": [
|
||||
"api",
|
||||
"auth",
|
||||
"auth",
|
||||
"authentication",
|
||||
"authorisation",
|
||||
"authorization",
|
||||
"oauth",
|
||||
"oauth 2",
|
||||
"oauth 2.0",
|
||||
"oauth2",
|
||||
"protect",
|
||||
"resource",
|
||||
"secure",
|
||||
"server"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "league/plates",
|
||||
"version": "3.1.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/thephpleague/plates.git",
|
||||
"reference": "2d8569e9f140a70d6a05db38006926f7547cb802"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/thephpleague/plates/zipball/2d8569e9f140a70d6a05db38006926f7547cb802",
|
||||
"reference": "2d8569e9f140a70d6a05db38006926f7547cb802",
|
||||
"shasum": ""
|
||||
},
|
||||
"require-dev": {
|
||||
"mikey179/vfsstream": "~1.4.0",
|
||||
"phpunit/phpunit": "~4.0",
|
||||
"squizlabs/php_codesniffer": "~1.5"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "3.0-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"League\\Plates\\": "src"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Jonathan Reinink",
|
||||
"email": "jonathan@reinink.ca",
|
||||
"role": "Developer"
|
||||
}
|
||||
],
|
||||
"description": "Plates, the native PHP template system that's fast, easy to use and easy to extend.",
|
||||
"homepage": "http://platesphp.com",
|
||||
"keywords": [
|
||||
"league",
|
||||
"package",
|
||||
"templates",
|
||||
"templating",
|
||||
"views"
|
||||
],
|
||||
"time": "2015-07-09 02:14:40"
|
||||
},
|
||||
{
|
||||
"name": "nikic/fast-route",
|
||||
"version": "v0.6.0",
|
||||
@@ -314,54 +77,6 @@
|
||||
],
|
||||
"time": "2015-06-18 19:15:47"
|
||||
},
|
||||
{
|
||||
"name": "paragonie/random_compat",
|
||||
"version": "v1.4.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/paragonie/random_compat.git",
|
||||
"reference": "c7e26a21ba357863de030f0b9e701c7d04593774"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/paragonie/random_compat/zipball/c7e26a21ba357863de030f0b9e701c7d04593774",
|
||||
"reference": "c7e26a21ba357863de030f0b9e701c7d04593774",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=5.2.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "4.*|5.*"
|
||||
},
|
||||
"suggest": {
|
||||
"ext-libsodium": "Provides a modern crypto API that can be used to generate random bytes."
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"files": [
|
||||
"lib/random.php"
|
||||
]
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Paragon Initiative Enterprises",
|
||||
"email": "security@paragonie.com",
|
||||
"homepage": "https://paragonie.com"
|
||||
}
|
||||
],
|
||||
"description": "PHP 5.x polyfill for random_bytes() and random_int() from PHP 7",
|
||||
"keywords": [
|
||||
"csprng",
|
||||
"pseudorandom",
|
||||
"random"
|
||||
],
|
||||
"time": "2016-03-18 20:34:03"
|
||||
},
|
||||
{
|
||||
"name": "pimple/pimple",
|
||||
"version": "v3.0.2",
|
||||
@@ -524,12 +239,167 @@
|
||||
"time": "2015-12-07 14:11:09"
|
||||
}
|
||||
],
|
||||
"packages-dev": [],
|
||||
"packages-dev": [
|
||||
{
|
||||
"name": "lcobucci/jwt",
|
||||
"version": "3.1.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/lcobucci/jwt.git",
|
||||
"reference": "afea8e682e911a21574fd8519321b32522fa25b5"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/lcobucci/jwt/zipball/afea8e682e911a21574fd8519321b32522fa25b5",
|
||||
"reference": "afea8e682e911a21574fd8519321b32522fa25b5",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"ext-openssl": "*",
|
||||
"php": ">=5.5"
|
||||
},
|
||||
"require-dev": {
|
||||
"mdanter/ecc": "~0.3",
|
||||
"mikey179/vfsstream": "~1.5",
|
||||
"phpmd/phpmd": "~2.2",
|
||||
"phpunit/php-invoker": "~1.1",
|
||||
"phpunit/phpunit": "~4.5",
|
||||
"squizlabs/php_codesniffer": "~2.3"
|
||||
},
|
||||
"suggest": {
|
||||
"mdanter/ecc": "Required to use Elliptic Curves based algorithms."
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "3.1-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Lcobucci\\JWT\\": "src"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"BSD-3-Clause"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Luís Otávio Cobucci Oblonczyk",
|
||||
"email": "lcobucci@gmail.com",
|
||||
"role": "Developer"
|
||||
}
|
||||
],
|
||||
"description": "A simple library to work with JSON Web Token and JSON Web Signature",
|
||||
"keywords": [
|
||||
"JWS",
|
||||
"jwt"
|
||||
],
|
||||
"time": "2016-03-24 22:46:13"
|
||||
},
|
||||
{
|
||||
"name": "league/event",
|
||||
"version": "2.1.2",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/thephpleague/event.git",
|
||||
"reference": "e4bfc88dbcb60c8d8a2939a71f9813e141bbe4cd"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/thephpleague/event/zipball/e4bfc88dbcb60c8d8a2939a71f9813e141bbe4cd",
|
||||
"reference": "e4bfc88dbcb60c8d8a2939a71f9813e141bbe4cd",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=5.4.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"henrikbjorn/phpspec-code-coverage": "~1.0.1",
|
||||
"phpspec/phpspec": "~2.0.0"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "2.2-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"League\\Event\\": "src/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Frank de Jonge",
|
||||
"email": "info@frenky.net"
|
||||
}
|
||||
],
|
||||
"description": "Event package",
|
||||
"keywords": [
|
||||
"emitter",
|
||||
"event",
|
||||
"listener"
|
||||
],
|
||||
"time": "2015-05-21 12:24:47"
|
||||
},
|
||||
{
|
||||
"name": "paragonie/random_compat",
|
||||
"version": "v1.4.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/paragonie/random_compat.git",
|
||||
"reference": "c7e26a21ba357863de030f0b9e701c7d04593774"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/paragonie/random_compat/zipball/c7e26a21ba357863de030f0b9e701c7d04593774",
|
||||
"reference": "c7e26a21ba357863de030f0b9e701c7d04593774",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=5.2.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "4.*|5.*"
|
||||
},
|
||||
"suggest": {
|
||||
"ext-libsodium": "Provides a modern crypto API that can be used to generate random bytes."
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"files": [
|
||||
"lib/random.php"
|
||||
]
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Paragon Initiative Enterprises",
|
||||
"email": "security@paragonie.com",
|
||||
"homepage": "https://paragonie.com"
|
||||
}
|
||||
],
|
||||
"description": "PHP 5.x polyfill for random_bytes() and random_int() from PHP 7",
|
||||
"keywords": [
|
||||
"csprng",
|
||||
"pseudorandom",
|
||||
"random"
|
||||
],
|
||||
"time": "2016-03-18 20:34:03"
|
||||
}
|
||||
],
|
||||
"aliases": [],
|
||||
"minimum-stability": "stable",
|
||||
"stability-flags": {
|
||||
"league/oauth2-server": 20
|
||||
},
|
||||
"stability-flags": [],
|
||||
"prefer-stable": false,
|
||||
"prefer-lowest": false,
|
||||
"platform": [],
|
||||
|
@@ -1,9 +1,7 @@
|
||||
<?php
|
||||
|
||||
use League\OAuth2\Server\Server;
|
||||
use League\OAuth2\Server\ResourceServer;
|
||||
use OAuth2ServerExamples\Repositories\AccessTokenRepository;
|
||||
use OAuth2ServerExamples\Repositories\ClientRepository;
|
||||
use OAuth2ServerExamples\Repositories\ScopeRepository;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
use Psr\Http\Message\ServerRequestInterface;
|
||||
use Slim\App;
|
||||
@@ -11,64 +9,64 @@ use Slim\App;
|
||||
include __DIR__ . '/../vendor/autoload.php';
|
||||
|
||||
$app = new App([
|
||||
'settings' => [
|
||||
'displayErrorDetails' => true,
|
||||
],
|
||||
Server::class => function () {
|
||||
// Setup the authorization server
|
||||
$server = new Server(
|
||||
new ClientRepository(),
|
||||
new AccessTokenRepository(),
|
||||
new ScopeRepository(),
|
||||
'file://' . __DIR__ . '/../private.key',
|
||||
'file://' . __DIR__ . '/../public.key'
|
||||
// Add the resource server to the DI container
|
||||
ResourceServer::class => function () {
|
||||
$server = new ResourceServer(
|
||||
new AccessTokenRepository(), // instance of AccessTokenRepositoryInterface
|
||||
'file://' . __DIR__ . '/../public.key' // the authorization server's public key
|
||||
);
|
||||
|
||||
return $server;
|
||||
},
|
||||
]);
|
||||
|
||||
// Add the resource server middleware which will intercept and validate requests
|
||||
$app->add(
|
||||
new \League\OAuth2\Server\Middleware\ResourceServerMiddleware(
|
||||
$app->getContainer()->get(Server::class)
|
||||
$app->getContainer()->get(ResourceServer::class)
|
||||
)
|
||||
);
|
||||
|
||||
$app->get('/users', function (ServerRequestInterface $request, ResponseInterface $response) use ($app) {
|
||||
// An example endpoint secured with OAuth 2.0
|
||||
$app->get(
|
||||
'/users',
|
||||
function (ServerRequestInterface $request, ResponseInterface $response) use ($app) {
|
||||
$users = [
|
||||
[
|
||||
'id' => 123,
|
||||
'name' => 'Alex',
|
||||
'email' => 'alex@thephpleague.com',
|
||||
],
|
||||
[
|
||||
'id' => 124,
|
||||
'name' => 'Frank',
|
||||
'email' => 'frank@thephpleague.com',
|
||||
],
|
||||
[
|
||||
'id' => 125,
|
||||
'name' => 'Phil',
|
||||
'email' => 'phil@thephpleague.com',
|
||||
],
|
||||
];
|
||||
|
||||
$users = [
|
||||
[
|
||||
'id' => 123,
|
||||
'name' => 'Alex',
|
||||
'email' => 'alex@thephpleague.com',
|
||||
],
|
||||
[
|
||||
'id' => 124,
|
||||
'name' => 'Frank',
|
||||
'email' => 'frank@thephpleague.com',
|
||||
],
|
||||
[
|
||||
'id' => 125,
|
||||
'name' => 'Phil',
|
||||
'email' => 'phil@thephpleague.com',
|
||||
],
|
||||
];
|
||||
|
||||
if (in_array('basic', $request->getAttribute('oauth_scopes')) === false) {
|
||||
for ($i = 0; $i < count($users); $i++) {
|
||||
unset($users[$i]['name']);
|
||||
// If the access token doesn't have the `basic` scope hide users' names
|
||||
if (in_array('basic', $request->getAttribute('oauth_scopes')) === false) {
|
||||
for ($i = 0; $i < count($users); $i++) {
|
||||
unset($users[$i]['name']);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (in_array('email', $request->getAttribute('oauth_scopes')) === false) {
|
||||
for ($i = 0; $i < count($users); $i++) {
|
||||
unset($users[$i]['email']);
|
||||
// If the access token doesn't have the `email` scope hide users' email addresses
|
||||
if (in_array('email', $request->getAttribute('oauth_scopes')) === false) {
|
||||
for ($i = 0; $i < count($users); $i++) {
|
||||
unset($users[$i]['email']);
|
||||
}
|
||||
}
|
||||
|
||||
$response->getBody()->write(json_encode($users));
|
||||
|
||||
return $response->withStatus(200);
|
||||
}
|
||||
|
||||
$response->getBody()->write(json_encode($users));
|
||||
|
||||
return $response->withStatus(200);
|
||||
});
|
||||
);
|
||||
|
||||
$app->run();
|
||||
|
@@ -1,14 +1,21 @@
|
||||
<?php
|
||||
/**
|
||||
* @author Alex Bilbie <hello@alexbilbie.com>
|
||||
* @copyright Copyright (c) Alex Bilbie
|
||||
* @license http://mit-license.org/
|
||||
*
|
||||
* @link https://github.com/thephpleague/oauth2-server
|
||||
*/
|
||||
|
||||
use League\OAuth2\Server\AuthorizationServer;
|
||||
use League\OAuth2\Server\Exception\OAuthServerException;
|
||||
use League\OAuth2\Server\Grant\AuthCodeGrant;
|
||||
use League\OAuth2\Server\Server;
|
||||
use OAuth2ServerExamples\Entities\UserEntity;
|
||||
use OAuth2ServerExamples\Repositories\AccessTokenRepository;
|
||||
use OAuth2ServerExamples\Repositories\AuthCodeRepository;
|
||||
use OAuth2ServerExamples\Repositories\ClientRepository;
|
||||
use OAuth2ServerExamples\Repositories\RefreshTokenRepository;
|
||||
use OAuth2ServerExamples\Repositories\ScopeRepository;
|
||||
use OAuth2ServerExamples\Repositories\UserRepository;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
use Psr\Http\Message\ServerRequestInterface;
|
||||
use Slim\App;
|
||||
@@ -20,20 +27,19 @@ $app = new App([
|
||||
'settings' => [
|
||||
'displayErrorDetails' => true,
|
||||
],
|
||||
Server::class => function () {
|
||||
AuthorizationServer::class => function () {
|
||||
// Init our repositories
|
||||
$clientRepository = new ClientRepository();
|
||||
$scopeRepository = new ScopeRepository();
|
||||
$accessTokenRepository = new AccessTokenRepository();
|
||||
$authCodeRepository = new AuthCodeRepository();
|
||||
$refreshTokenRepository = new RefreshTokenRepository();
|
||||
$userRepository = new UserRepository();
|
||||
|
||||
$privateKeyPath = 'file://' . __DIR__ . '/../private.key';
|
||||
$publicKeyPath = 'file://' . __DIR__ . '/../public.key';
|
||||
|
||||
// Setup the authorization server
|
||||
$server = new Server(
|
||||
$server = new AuthorizationServer(
|
||||
$clientRepository,
|
||||
$accessTokenRepository,
|
||||
$scopeRepository,
|
||||
@@ -46,7 +52,6 @@ $app = new App([
|
||||
new AuthCodeGrant(
|
||||
$authCodeRepository,
|
||||
$refreshTokenRepository,
|
||||
$userRepository,
|
||||
new \DateInterval('PT10M')
|
||||
),
|
||||
new \DateInterval('PT1H')
|
||||
@@ -56,12 +61,24 @@ $app = new App([
|
||||
},
|
||||
]);
|
||||
|
||||
$app->any('/authorize', function (ServerRequestInterface $request, ResponseInterface $response) use ($app) {
|
||||
/* @var \League\OAuth2\Server\Server $server */
|
||||
$server = $app->getContainer()->get(Server::class);
|
||||
$app->get('/authorize', function (ServerRequestInterface $request, ResponseInterface $response) use ($app) {
|
||||
/* @var \League\OAuth2\Server\AuthorizationServer $server */
|
||||
$server = $app->getContainer()->get(AuthorizationServer::class);
|
||||
|
||||
try {
|
||||
return $server->respondToRequest($request, $response);
|
||||
// Validate the HTTP request and return an AuthorizationRequest object.
|
||||
// The auth request object can be serialized into a user's session
|
||||
$authRequest = $server->validateAuthorizationRequest($request);
|
||||
|
||||
// Once the user has logged in set the user on the AuthorizationRequest
|
||||
$authRequest->setUser(new UserEntity());
|
||||
|
||||
// Once the user has approved or denied the client update the status
|
||||
// (true = approved, false = denied)
|
||||
$authRequest->setAuthorizationApproved(true);
|
||||
|
||||
// Return the HTTP redirect response
|
||||
return $server->completeAuthorizationRequest($authRequest, $response);
|
||||
} catch (OAuthServerException $exception) {
|
||||
return $exception->generateHttpResponse($response);
|
||||
} catch (\Exception $exception) {
|
||||
@@ -73,11 +90,11 @@ $app->any('/authorize', function (ServerRequestInterface $request, ResponseInter
|
||||
});
|
||||
|
||||
$app->post('/access_token', function (ServerRequestInterface $request, ResponseInterface $response) use ($app) {
|
||||
/* @var \League\OAuth2\Server\Server $server */
|
||||
$server = $app->getContainer()->get(Server::class);
|
||||
/* @var \League\OAuth2\Server\AuthorizationServer $server */
|
||||
$server = $app->getContainer()->get(AuthorizationServer::class);
|
||||
|
||||
try {
|
||||
return $server->respondToRequest($request, $response);
|
||||
return $server->respondToAccessTokenRequest($request, $response);
|
||||
} catch (OAuthServerException $exception) {
|
||||
return $exception->generateHttpResponse($response);
|
||||
} catch (\Exception $exception) {
|
||||
|
@@ -1,8 +1,14 @@
|
||||
<?php
|
||||
/**
|
||||
* @author Alex Bilbie <hello@alexbilbie.com>
|
||||
* @copyright Copyright (c) Alex Bilbie
|
||||
* @license http://mit-license.org/
|
||||
*
|
||||
* @link https://github.com/thephpleague/oauth2-server
|
||||
*/
|
||||
|
||||
use League\OAuth2\Server\AuthorizationServer;
|
||||
use League\OAuth2\Server\Exception\OAuthServerException;
|
||||
use League\OAuth2\Server\Grant\ClientCredentialsGrant;
|
||||
use League\OAuth2\Server\Server;
|
||||
use OAuth2ServerExamples\Repositories\AccessTokenRepository;
|
||||
use OAuth2ServerExamples\Repositories\ClientRepository;
|
||||
use OAuth2ServerExamples\Repositories\ScopeRepository;
|
||||
@@ -14,31 +20,33 @@ use Zend\Diactoros\Stream;
|
||||
include __DIR__ . '/../vendor/autoload.php';
|
||||
|
||||
$app = new App([
|
||||
'settings' => [
|
||||
'settings' => [
|
||||
'displayErrorDetails' => true,
|
||||
],
|
||||
Server::class => function () {
|
||||
AuthorizationServer::class => function () {
|
||||
// Init our repositories
|
||||
$clientRepository = new ClientRepository();
|
||||
$accessTokenRepository = new AccessTokenRepository();
|
||||
$scopeRepository = new ScopeRepository();
|
||||
$clientRepository = new ClientRepository(); // instance of ClientRepositoryInterface
|
||||
$scopeRepository = new ScopeRepository(); // instance of ScopeRepositoryInterface
|
||||
$accessTokenRepository = new AccessTokenRepository(); // instance of AccessTokenRepositoryInterface
|
||||
|
||||
$privateKeyPath = 'file://' . __DIR__ . '/../private.key';
|
||||
$publicKeyPath = 'file://' . __DIR__ . '/../public.key';
|
||||
// Path to public and private keys
|
||||
$privateKey = 'file://' . __DIR__ . '/../private.key';
|
||||
//$privateKey = new CryptKey('file://path/to/private.key', 'passphrase'); // if private key has a pass phrase
|
||||
$publicKey = 'file://' . __DIR__ . '/../public.key';
|
||||
|
||||
// Setup the authorization server
|
||||
$server = new Server(
|
||||
$server = new AuthorizationServer(
|
||||
$clientRepository,
|
||||
$accessTokenRepository,
|
||||
$scopeRepository,
|
||||
$privateKeyPath,
|
||||
$publicKeyPath
|
||||
$privateKey,
|
||||
$publicKey
|
||||
);
|
||||
|
||||
// Enable the client credentials grant on the server with a token TTL of 1 hour
|
||||
// Enable the client credentials grant on the server
|
||||
$server->enableGrantType(
|
||||
new ClientCredentialsGrant(),
|
||||
new \DateInterval('PT1H')
|
||||
new \League\OAuth2\Server\Grant\ClientCredentialsGrant(),
|
||||
new \DateInterval('PT1H') // access tokens will expire after 1 hour
|
||||
);
|
||||
|
||||
return $server;
|
||||
@@ -46,14 +54,21 @@ $app = new App([
|
||||
]);
|
||||
|
||||
$app->post('/access_token', function (ServerRequestInterface $request, ResponseInterface $response) use ($app) {
|
||||
/* @var \League\OAuth2\Server\Server $server */
|
||||
$server = $app->getContainer()->get(Server::class);
|
||||
|
||||
/* @var \League\OAuth2\Server\AuthorizationServer $server */
|
||||
$server = $app->getContainer()->get(AuthorizationServer::class);
|
||||
|
||||
try {
|
||||
return $server->respondToRequest($request, $response);
|
||||
|
||||
// Try to respond to the request
|
||||
return $server->respondToAccessTokenRequest($request, $response);
|
||||
} catch (OAuthServerException $exception) {
|
||||
|
||||
// All instances of OAuthServerException can be formatted into a HTTP response
|
||||
return $exception->generateHttpResponse($response);
|
||||
} catch (\Exception $exception) {
|
||||
|
||||
// Unknown exception
|
||||
$body = new Stream('php://temp', 'r+');
|
||||
$body->write($exception->getMessage());
|
||||
|
||||
|
@@ -1,12 +1,19 @@
|
||||
<?php
|
||||
/**
|
||||
* @author Alex Bilbie <hello@alexbilbie.com>
|
||||
* @copyright Copyright (c) Alex Bilbie
|
||||
* @license http://mit-license.org/
|
||||
*
|
||||
* @link https://github.com/thephpleague/oauth2-server
|
||||
*/
|
||||
|
||||
use League\OAuth2\Server\AuthorizationServer;
|
||||
use League\OAuth2\Server\Exception\OAuthServerException;
|
||||
use League\OAuth2\Server\Grant\ImplicitGrant;
|
||||
use League\OAuth2\Server\Server;
|
||||
use OAuth2ServerExamples\Entities\UserEntity;
|
||||
use OAuth2ServerExamples\Repositories\AccessTokenRepository;
|
||||
use OAuth2ServerExamples\Repositories\ClientRepository;
|
||||
use OAuth2ServerExamples\Repositories\ScopeRepository;
|
||||
use OAuth2ServerExamples\Repositories\UserRepository;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
use Psr\Http\Message\ServerRequestInterface;
|
||||
use Slim\App;
|
||||
@@ -18,18 +25,17 @@ $app = new App([
|
||||
'settings' => [
|
||||
'displayErrorDetails' => true,
|
||||
],
|
||||
Server::class => function () {
|
||||
AuthorizationServer::class => function () {
|
||||
// Init our repositories
|
||||
$clientRepository = new ClientRepository();
|
||||
$scopeRepository = new ScopeRepository();
|
||||
$accessTokenRepository = new AccessTokenRepository();
|
||||
$userRepository = new UserRepository();
|
||||
|
||||
$privateKeyPath = 'file://' . __DIR__ . '/../private.key';
|
||||
$publicKeyPath = 'file://' . __DIR__ . '/../public.key';
|
||||
|
||||
// Setup the authorization server
|
||||
$server = new Server(
|
||||
$server = new AuthorizationServer(
|
||||
$clientRepository,
|
||||
$accessTokenRepository,
|
||||
$scopeRepository,
|
||||
@@ -38,21 +44,30 @@ $app = new App([
|
||||
);
|
||||
|
||||
// Enable the implicit grant on the server with a token TTL of 1 hour
|
||||
$server->enableGrantType(
|
||||
new ImplicitGrant($userRepository),
|
||||
new \DateInterval('PT1H')
|
||||
);
|
||||
$server->enableGrantType(new ImplicitGrant(new \DateInterval('PT1H')));
|
||||
|
||||
return $server;
|
||||
},
|
||||
]);
|
||||
|
||||
$app->any('/authorize', function (ServerRequestInterface $request, ResponseInterface $response) use ($app) {
|
||||
/* @var \League\OAuth2\Server\Server $server */
|
||||
$server = $app->getContainer()->get(Server::class);
|
||||
$app->get('/authorize', function (ServerRequestInterface $request, ResponseInterface $response) use ($app) {
|
||||
/* @var \League\OAuth2\Server\AuthorizationServer $server */
|
||||
$server = $app->getContainer()->get(AuthorizationServer::class);
|
||||
|
||||
try {
|
||||
return $server->respondToRequest($request, $response);
|
||||
// Validate the HTTP request and return an AuthorizationRequest object.
|
||||
// The auth request object can be serialized into a user's session
|
||||
$authRequest = $server->validateAuthorizationRequest($request);
|
||||
|
||||
// Once the user has logged in set the user on the AuthorizationRequest
|
||||
$authRequest->setUser(new UserEntity());
|
||||
|
||||
// Once the user has approved or denied the client update the status
|
||||
// (true = approved, false = denied)
|
||||
$authRequest->setAuthorizationApproved(true);
|
||||
|
||||
// Return the HTTP redirect response
|
||||
return $server->completeAuthorizationRequest($authRequest, $response);
|
||||
} catch (OAuthServerException $exception) {
|
||||
return $exception->generateHttpResponse($response);
|
||||
} catch (\Exception $exception) {
|
||||
|
@@ -1,16 +1,22 @@
|
||||
<?php
|
||||
/**
|
||||
* @author Alex Bilbie <hello@alexbilbie.com>
|
||||
* @copyright Copyright (c) Alex Bilbie
|
||||
* @license http://mit-license.org/
|
||||
*
|
||||
* @link https://github.com/thephpleague/oauth2-server
|
||||
*/
|
||||
|
||||
use League\OAuth2\Server\AuthorizationServer;
|
||||
use League\OAuth2\Server\Grant\AuthCodeGrant;
|
||||
use League\OAuth2\Server\Grant\RefreshTokenGrant;
|
||||
use League\OAuth2\Server\Middleware\AuthenticationServerMiddleware;
|
||||
use League\OAuth2\Server\Middleware\AuthorizationServerMiddleware;
|
||||
use League\OAuth2\Server\Middleware\ResourceServerMiddleware;
|
||||
use League\OAuth2\Server\Server;
|
||||
use OAuth2ServerExamples\Repositories\AccessTokenRepository;
|
||||
use OAuth2ServerExamples\Repositories\AuthCodeRepository;
|
||||
use OAuth2ServerExamples\Repositories\ClientRepository;
|
||||
use OAuth2ServerExamples\Repositories\RefreshTokenRepository;
|
||||
use OAuth2ServerExamples\Repositories\ScopeRepository;
|
||||
use OAuth2ServerExamples\Repositories\UserRepository;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
use Psr\Http\Message\ServerRequestInterface;
|
||||
use Slim\App;
|
||||
@@ -19,23 +25,22 @@ use Zend\Diactoros\Stream;
|
||||
include __DIR__ . '/../vendor/autoload.php';
|
||||
|
||||
$app = new App([
|
||||
'settings' => [
|
||||
'settings' => [
|
||||
'displayErrorDetails' => true,
|
||||
],
|
||||
Server::class => function () {
|
||||
AuthorizationServer::class => function () {
|
||||
// Init our repositories
|
||||
$clientRepository = new ClientRepository();
|
||||
$accessTokenRepository = new AccessTokenRepository();
|
||||
$scopeRepository = new ScopeRepository();
|
||||
$authCodeRepository = new AuthCodeRepository();
|
||||
$refreshTokenRepository = new RefreshTokenRepository();
|
||||
$userRepository = new UserRepository();
|
||||
|
||||
$privateKeyPath = 'file://' . __DIR__ . '/../private.key';
|
||||
$publicKeyPath = 'file://' . __DIR__ . '/../public.key';
|
||||
|
||||
// Setup the authorization server
|
||||
$server = new Server(
|
||||
$server = new AuthorizationServer(
|
||||
$clientRepository,
|
||||
$accessTokenRepository,
|
||||
$scopeRepository,
|
||||
@@ -48,7 +53,6 @@ $app = new App([
|
||||
new AuthCodeGrant(
|
||||
$authCodeRepository,
|
||||
$refreshTokenRepository,
|
||||
$userRepository,
|
||||
new \DateInterval('PT10M')
|
||||
),
|
||||
new \DateInterval('PT1H')
|
||||
@@ -66,7 +70,7 @@ $app = new App([
|
||||
|
||||
// Access token issuer
|
||||
$app->post('/access_token', function () {
|
||||
})->add(new AuthenticationServerMiddleware($app->getContainer()->get(Server::class)));
|
||||
})->add(new AuthorizationServerMiddleware($app->getContainer()->get(AuthorizationServer::class)));
|
||||
|
||||
// Secured API
|
||||
$app->group('/api', function () {
|
||||
@@ -90,6 +94,6 @@ $app->group('/api', function () {
|
||||
|
||||
return $response->withBody($body);
|
||||
});
|
||||
})->add(new ResourceServerMiddleware($app->getContainer()->get(Server::class)));
|
||||
})->add(new ResourceServerMiddleware($app->getContainer()->get(AuthorizationServer::class)));
|
||||
|
||||
$app->run();
|
||||
|
@@ -1,8 +1,8 @@
|
||||
<?php
|
||||
|
||||
use League\OAuth2\Server\AuthorizationServer;
|
||||
use League\OAuth2\Server\Exception\OAuthServerException;
|
||||
use League\OAuth2\Server\Grant\PasswordGrant;
|
||||
use League\OAuth2\Server\Server;
|
||||
use OAuth2ServerExamples\Repositories\AccessTokenRepository;
|
||||
use OAuth2ServerExamples\Repositories\ClientRepository;
|
||||
use OAuth2ServerExamples\Repositories\RefreshTokenRepository;
|
||||
@@ -11,58 +11,62 @@ use OAuth2ServerExamples\Repositories\UserRepository;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
use Psr\Http\Message\ServerRequestInterface;
|
||||
use Slim\App;
|
||||
use Zend\Diactoros\Stream;
|
||||
|
||||
include __DIR__ . '/../vendor/autoload.php';
|
||||
|
||||
$app = new App([
|
||||
'settings' => [
|
||||
'displayErrorDetails' => true,
|
||||
],
|
||||
Server::class => function () {
|
||||
// Init our repositories
|
||||
$clientRepository = new ClientRepository();
|
||||
$accessTokenRepository = new AccessTokenRepository();
|
||||
$scopeRepository = new ScopeRepository();
|
||||
$userRepository = new UserRepository();
|
||||
$refreshTokenRepository = new RefreshTokenRepository();
|
||||
|
||||
$privateKeyPath = 'file://' . __DIR__ . '/../private.key';
|
||||
$publicKeyPath = 'file://' . __DIR__ . '/../public.key';
|
||||
// Add the authorization server to the DI container
|
||||
AuthorizationServer::class => function () {
|
||||
|
||||
// Setup the authorization server
|
||||
$server = new Server(
|
||||
$clientRepository,
|
||||
$accessTokenRepository,
|
||||
$scopeRepository,
|
||||
$privateKeyPath,
|
||||
$publicKeyPath
|
||||
$server = new AuthorizationServer(
|
||||
new ClientRepository(), // instance of ClientRepositoryInterface
|
||||
new AccessTokenRepository(), // instance of AccessTokenRepositoryInterface
|
||||
new ScopeRepository(), // instance of ScopeRepositoryInterface
|
||||
'file://' . __DIR__ . '/../private.key', // path to private key
|
||||
'file://' . __DIR__ . '/../public.key' // path to public key
|
||||
);
|
||||
|
||||
$grant = new PasswordGrant(
|
||||
new UserRepository(), // instance of UserRepositoryInterface
|
||||
new RefreshTokenRepository() // instance of RefreshTokenRepositoryInterface
|
||||
);
|
||||
$grant->setRefreshTokenTTL(new \DateInterval('P1M')); // refresh tokens will expire after 1 month
|
||||
|
||||
// Enable the password grant on the server with a token TTL of 1 hour
|
||||
$server->enableGrantType(
|
||||
new PasswordGrant($userRepository, $refreshTokenRepository),
|
||||
new \DateInterval('PT1H')
|
||||
$grant,
|
||||
new \DateInterval('PT1H') // access tokens will expire after 1 hour
|
||||
);
|
||||
|
||||
return $server;
|
||||
},
|
||||
]);
|
||||
|
||||
$app->post('/access_token', function (ServerRequestInterface $request, ResponseInterface $response) use ($app) {
|
||||
/* @var \League\OAuth2\Server\Server $server */
|
||||
$server = $app->getContainer()->get(Server::class);
|
||||
$app->post(
|
||||
'/access_token',
|
||||
function (ServerRequestInterface $request, ResponseInterface $response) use ($app) {
|
||||
|
||||
try {
|
||||
return $server->respondToRequest($request, $response);
|
||||
} catch (OAuthServerException $exception) {
|
||||
return $exception->generateHttpResponse($response);
|
||||
} catch (\Exception $exception) {
|
||||
$body = new Stream('php://temp', 'r+');
|
||||
$body->write($exception->getMessage());
|
||||
/* @var \League\OAuth2\Server\AuthorizationServer $server */
|
||||
$server = $app->getContainer()->get(AuthorizationServer::class);
|
||||
|
||||
return $response->withStatus(500)->withBody($body);
|
||||
try {
|
||||
|
||||
// Try to respond to the access token request
|
||||
return $server->respondToAccessTokenRequest($request, $response);
|
||||
} catch (OAuthServerException $exception) {
|
||||
|
||||
// All instances of OAuthServerException can be converted to a PSR-7 response
|
||||
return $exception->generateHttpResponse($response);
|
||||
} catch (\Exception $exception) {
|
||||
|
||||
// Catch unexpected exceptions
|
||||
$body = $response->getBody();
|
||||
$body->write($exception->getMessage());
|
||||
|
||||
return $response->withStatus(500)->withBody($body);
|
||||
}
|
||||
}
|
||||
});
|
||||
);
|
||||
|
||||
$app->run();
|
||||
|
@@ -1,8 +1,15 @@
|
||||
<?php
|
||||
/**
|
||||
* @author Alex Bilbie <hello@alexbilbie.com>
|
||||
* @copyright Copyright (c) Alex Bilbie
|
||||
* @license http://mit-license.org/
|
||||
*
|
||||
* @link https://github.com/thephpleague/oauth2-server
|
||||
*/
|
||||
|
||||
use League\OAuth2\Server\AuthorizationServer;
|
||||
use League\OAuth2\Server\Exception\OAuthServerException;
|
||||
use League\OAuth2\Server\Grant\RefreshTokenGrant;
|
||||
use League\OAuth2\Server\Server;
|
||||
use OAuth2ServerExamples\Repositories\AccessTokenRepository;
|
||||
use OAuth2ServerExamples\Repositories\ClientRepository;
|
||||
use OAuth2ServerExamples\Repositories\RefreshTokenRepository;
|
||||
@@ -18,7 +25,7 @@ $app = new App([
|
||||
'settings' => [
|
||||
'displayErrorDetails' => true,
|
||||
],
|
||||
Server::class => function () {
|
||||
AuthorizationServer::class => function () {
|
||||
// Init our repositories
|
||||
$clientRepository = new ClientRepository();
|
||||
$accessTokenRepository = new AccessTokenRepository();
|
||||
@@ -29,7 +36,7 @@ $app = new App([
|
||||
$publicKeyPath = 'file://' . __DIR__ . '/../public.key';
|
||||
|
||||
// Setup the authorization server
|
||||
$server = new Server(
|
||||
$server = new AuthorizationServer(
|
||||
$clientRepository,
|
||||
$accessTokenRepository,
|
||||
$scopeRepository,
|
||||
@@ -37,10 +44,13 @@ $app = new App([
|
||||
$publicKeyPath
|
||||
);
|
||||
|
||||
// Enable the refresh token grant on the server with a token TTL of 1 hour
|
||||
// Enable the refresh token grant on the server
|
||||
$grant = new RefreshTokenGrant($refreshTokenRepository);
|
||||
$grant->setRefreshTokenTTL(new \DateInterval('P1M')); // The refresh token will expire in 1 month
|
||||
|
||||
$server->enableGrantType(
|
||||
new RefreshTokenGrant($refreshTokenRepository),
|
||||
new \DateInterval('PT1H')
|
||||
$grant,
|
||||
new \DateInterval('PT1H') // The new access token will expire after 1 hour
|
||||
);
|
||||
|
||||
return $server;
|
||||
@@ -48,11 +58,11 @@ $app = new App([
|
||||
]);
|
||||
|
||||
$app->post('/access_token', function (ServerRequestInterface $request, ResponseInterface $response) use ($app) {
|
||||
/* @var \League\OAuth2\Server\Server $server */
|
||||
$server = $app->getContainer()->get(Server::class);
|
||||
/* @var \League\OAuth2\Server\AuthorizationServer $server */
|
||||
$server = $app->getContainer()->get(AuthorizationServer::class);
|
||||
|
||||
try {
|
||||
return $server->respondToRequest($request, $response);
|
||||
return $server->respondToAccessTokenRequest($request, $response);
|
||||
} catch (OAuthServerException $exception) {
|
||||
return $exception->generateHttpResponse($response);
|
||||
} catch (\Exception $exception) {
|
||||
|
20
examples/src/Entities/AccessTokenEntity.php
Normal file
20
examples/src/Entities/AccessTokenEntity.php
Normal 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;
|
||||
}
|
20
examples/src/Entities/AuthCodeEntity.php
Normal file
20
examples/src/Entities/AuthCodeEntity.php
Normal 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;
|
||||
}
|
@@ -1,85 +1,29 @@
|
||||
<?php
|
||||
/**
|
||||
* @author Alex Bilbie <hello@alexbilbie.com>
|
||||
* @copyright Copyright (c) Alex Bilbie
|
||||
* @license http://mit-license.org/
|
||||
*
|
||||
* @link https://github.com/thephpleague/oauth2-server
|
||||
*/
|
||||
|
||||
namespace OAuth2ServerExamples\Entities;
|
||||
|
||||
use League\OAuth2\Server\Entities\Interfaces\ClientEntityInterface;
|
||||
use League\OAuth2\Server\Entities\ClientEntityInterface;
|
||||
use League\OAuth2\Server\Entities\Traits\ClientTrait;
|
||||
use League\OAuth2\Server\Entities\Traits\EntityTrait;
|
||||
|
||||
class ClientEntity implements ClientEntityInterface
|
||||
{
|
||||
use EntityTrait;
|
||||
use EntityTrait, ClientTrait;
|
||||
|
||||
private $name;
|
||||
|
||||
private $secret;
|
||||
|
||||
private $redirectUri;
|
||||
|
||||
/**
|
||||
* Get the client's name.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getName()
|
||||
{
|
||||
return $this->name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the client's name.
|
||||
*
|
||||
* @param string $name
|
||||
*/
|
||||
public function setName($name)
|
||||
{
|
||||
$this->name = $name;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $secret
|
||||
*/
|
||||
public function setSecret($secret)
|
||||
public function setRedirectUri($uri)
|
||||
{
|
||||
$this->secret = $secret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the hashed client secret
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getSecret()
|
||||
{
|
||||
return $this->secret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the client's redirect uri.
|
||||
*
|
||||
* @param string $redirectUri
|
||||
*/
|
||||
public function setRedirectUri($redirectUri)
|
||||
{
|
||||
$this->redirectUri = $redirectUri;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the registered redirect URI.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getRedirectUri()
|
||||
{
|
||||
return $this->redirectUri;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the client is capable of keeping it's secrets secret.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function canKeepASecret()
|
||||
{
|
||||
return $this->secret !== null;
|
||||
$this->redirectUri = $uri;
|
||||
}
|
||||
}
|
||||
|
19
examples/src/Entities/RefreshTokenEntity.php
Normal file
19
examples/src/Entities/RefreshTokenEntity.php
Normal 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;
|
||||
}
|
@@ -1,8 +1,15 @@
|
||||
<?php
|
||||
/**
|
||||
* @author Alex Bilbie <hello@alexbilbie.com>
|
||||
* @copyright Copyright (c) Alex Bilbie
|
||||
* @license http://mit-license.org/
|
||||
*
|
||||
* @link https://github.com/thephpleague/oauth2-server
|
||||
*/
|
||||
|
||||
namespace OAuth2ServerExamples\Entities;
|
||||
|
||||
use League\OAuth2\Server\Entities\Interfaces\ScopeEntityInterface;
|
||||
use League\OAuth2\Server\Entities\ScopeEntityInterface;
|
||||
use League\OAuth2\Server\Entities\Traits\EntityTrait;
|
||||
|
||||
class ScopeEntity implements ScopeEntityInterface
|
||||
|
@@ -1,8 +1,15 @@
|
||||
<?php
|
||||
/**
|
||||
* @author Alex Bilbie <hello@alexbilbie.com>
|
||||
* @copyright Copyright (c) Alex Bilbie
|
||||
* @license http://mit-license.org/
|
||||
*
|
||||
* @link https://github.com/thephpleague/oauth2-server
|
||||
*/
|
||||
|
||||
namespace OAuth2ServerExamples\Entities;
|
||||
|
||||
use League\OAuth2\Server\Entities\Interfaces\UserEntityInterface;
|
||||
use League\OAuth2\Server\Entities\UserEntityInterface;
|
||||
|
||||
class UserEntity implements UserEntityInterface
|
||||
{
|
||||
|
@@ -1,41 +1,57 @@
|
||||
<?php
|
||||
/**
|
||||
* @author Alex Bilbie <hello@alexbilbie.com>
|
||||
* @copyright Copyright (c) Alex Bilbie
|
||||
* @license http://mit-license.org/
|
||||
*
|
||||
* @link https://github.com/thephpleague/oauth2-server
|
||||
*/
|
||||
|
||||
namespace OAuth2ServerExamples\Repositories;
|
||||
|
||||
use League\OAuth2\Server\Entities\Interfaces\AccessTokenEntityInterface;
|
||||
use League\OAuth2\Server\Entities\AccessTokenEntityInterface;
|
||||
use League\OAuth2\Server\Entities\ClientEntityInterface;
|
||||
use League\OAuth2\Server\Repositories\AccessTokenRepositoryInterface;
|
||||
use OAuth2ServerExamples\Entities\AccessTokenEntity;
|
||||
|
||||
class AccessTokenRepository implements AccessTokenRepositoryInterface
|
||||
{
|
||||
/**
|
||||
* Persists a new access token to permanent storage.
|
||||
*
|
||||
* @param \League\OAuth2\Server\Entities\Interfaces\AccessTokenEntityInterface $accessTokenEntity
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function persistNewAccessToken(AccessTokenEntityInterface $accessTokenEntity)
|
||||
{
|
||||
// TODO: Implement persistNewAccessToken() method.
|
||||
// Some logic here to save the access token to a database
|
||||
}
|
||||
|
||||
/**
|
||||
* Revoke an access token.
|
||||
*
|
||||
* @param string $tokenId
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function revokeAccessToken($tokenId)
|
||||
{
|
||||
// TODO: Implement revokeAccessToken() method.
|
||||
// Some logic here to revoke the access token
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the access token has been revoked.
|
||||
*
|
||||
* @param string $tokenId
|
||||
*
|
||||
* @return bool Return true if this token has been revoked
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function isAccessTokenRevoked($tokenId)
|
||||
{
|
||||
// TODO: Implement isAccessTokenRevoked() method.
|
||||
return false; // Access token hasn't been revoked
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getNewToken(ClientEntityInterface $clientEntity, array $scopes, $userIdentifier = null)
|
||||
{
|
||||
$accessToken = new AccessTokenEntity();
|
||||
$accessToken->setClient($clientEntity);
|
||||
foreach ($scopes as $scope) {
|
||||
$accessToken->addScope($scope);
|
||||
}
|
||||
$accessToken->setUserIdentifier($userIdentifier);
|
||||
|
||||
return $accessToken;
|
||||
}
|
||||
}
|
||||
|
@@ -1,41 +1,49 @@
|
||||
<?php
|
||||
/**
|
||||
* @author Alex Bilbie <hello@alexbilbie.com>
|
||||
* @copyright Copyright (c) Alex Bilbie
|
||||
* @license http://mit-license.org/
|
||||
*
|
||||
* @link https://github.com/thephpleague/oauth2-server
|
||||
*/
|
||||
|
||||
namespace OAuth2ServerExamples\Repositories;
|
||||
|
||||
use League\OAuth2\Server\Entities\Interfaces\AuthCodeEntityInterface;
|
||||
use League\OAuth2\Server\Entities\AuthCodeEntityInterface;
|
||||
use League\OAuth2\Server\Repositories\AuthCodeRepositoryInterface;
|
||||
use OAuth2ServerExamples\Entities\AuthCodeEntity;
|
||||
|
||||
class AuthCodeRepository implements AuthCodeRepositoryInterface
|
||||
{
|
||||
/**
|
||||
* Persists a new auth code to permanent storage.
|
||||
*
|
||||
* @param \League\OAuth2\Server\Entities\Interfaces\AuthCodeEntityInterface $authCodeEntity
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function persistNewAuthCode(AuthCodeEntityInterface $authCodeEntity)
|
||||
{
|
||||
// TODO: Implement persistNewAuthCode() method.
|
||||
// Some logic to persist the auth code to a database
|
||||
}
|
||||
|
||||
/**
|
||||
* Revoke an auth code.
|
||||
*
|
||||
* @param string $codeId
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function revokeAuthCode($codeId)
|
||||
{
|
||||
// TODO: Implement revokeAuthCode() method.
|
||||
// Some logic to revoke the auth code in a database
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the auth code has been revoked.
|
||||
*
|
||||
* @param string $codeId
|
||||
*
|
||||
* @return bool Return true if this code has been revoked
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function isAuthCodeRevoked($codeId)
|
||||
{
|
||||
// TODO: Implement isAuthCodeRevoked() method.
|
||||
return false; // The auth code has not been revoked
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getNewAuthCode()
|
||||
{
|
||||
return new AuthCodeEntity();
|
||||
}
|
||||
}
|
||||
|
@@ -1,4 +1,11 @@
|
||||
<?php
|
||||
/**
|
||||
* @author Alex Bilbie <hello@alexbilbie.com>
|
||||
* @copyright Copyright (c) Alex Bilbie
|
||||
* @license http://mit-license.org/
|
||||
*
|
||||
* @link https://github.com/thephpleague/oauth2-server
|
||||
*/
|
||||
|
||||
namespace OAuth2ServerExamples\Repositories;
|
||||
|
||||
@@ -10,13 +17,14 @@ class ClientRepository implements ClientRepositoryInterface
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getClientEntity($clientIdentifier, $clientSecret = null, $redirectUri = null, $grantType = null)
|
||||
public function getClientEntity($clientIdentifier, $grantType, $clientSecret = null, $mustValidateSecret = true)
|
||||
{
|
||||
$clients = [
|
||||
'myawesomeapp' => [
|
||||
'secret' => password_hash('abc123', PASSWORD_BCRYPT),
|
||||
'name' => 'My Awesome App',
|
||||
'redirect_uri' => 'http://foo/bar',
|
||||
'secret' => password_hash('abc123', PASSWORD_BCRYPT),
|
||||
'name' => 'My Awesome App',
|
||||
'redirect_uri' => 'http://foo/bar',
|
||||
'is_confidential' => true,
|
||||
],
|
||||
];
|
||||
|
||||
@@ -25,11 +33,18 @@ class ClientRepository implements ClientRepositoryInterface
|
||||
return;
|
||||
}
|
||||
|
||||
if (
|
||||
$mustValidateSecret === true
|
||||
&& $clients[$clientIdentifier]['is_confidential'] === true
|
||||
&& password_verify($clientSecret, $clients[$clientIdentifier]['secret']) === false
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
$client = new ClientEntity();
|
||||
$client->setIdentifier($clientIdentifier);
|
||||
$client->setName($clients[$clientIdentifier]['name']);
|
||||
$client->setRedirectUri($clients[$clientIdentifier]['redirect_uri']);
|
||||
$client->setSecret($clients[$clientIdentifier]['secret']);
|
||||
|
||||
return $client;
|
||||
}
|
||||
|
@@ -1,41 +1,49 @@
|
||||
<?php
|
||||
/**
|
||||
* @author Alex Bilbie <hello@alexbilbie.com>
|
||||
* @copyright Copyright (c) Alex Bilbie
|
||||
* @license http://mit-license.org/
|
||||
*
|
||||
* @link https://github.com/thephpleague/oauth2-server
|
||||
*/
|
||||
|
||||
namespace OAuth2ServerExamples\Repositories;
|
||||
|
||||
use League\OAuth2\Server\Entities\Interfaces\RefreshTokenEntityInterface;
|
||||
use League\OAuth2\Server\Entities\RefreshTokenEntityInterface;
|
||||
use League\OAuth2\Server\Repositories\RefreshTokenRepositoryInterface;
|
||||
use OAuth2ServerExamples\Entities\RefreshTokenEntity;
|
||||
|
||||
class RefreshTokenRepository implements RefreshTokenRepositoryInterface
|
||||
{
|
||||
/**
|
||||
* Create a new refresh token_name.
|
||||
*
|
||||
* @param \League\OAuth2\Server\Entities\Interfaces\RefreshTokenEntityInterface $refreshTokenEntityInterface
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function persistNewRefreshToken(RefreshTokenEntityInterface $refreshTokenEntityInterface)
|
||||
{
|
||||
// TODO: Implement persistNewRefreshToken() method.
|
||||
// Some logic to persist the refresh token in a database
|
||||
}
|
||||
|
||||
/**
|
||||
* Revoke the refresh token.
|
||||
*
|
||||
* @param string $tokenId
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function revokeRefreshToken($tokenId)
|
||||
{
|
||||
// TODO: Implement revokeRefreshToken() method.
|
||||
// Some logic to revoke the refresh token in a database
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the refresh token has been revoked.
|
||||
*
|
||||
* @param string $tokenId
|
||||
*
|
||||
* @return bool Return true if this token has been revoked
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function isRefreshTokenRevoked($tokenId)
|
||||
{
|
||||
// TODO: Implement isRefreshTokenRevoked() method.
|
||||
return false; // The refresh token has not been revoked
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getNewRefreshToken()
|
||||
{
|
||||
return new RefreshTokenEntity();
|
||||
}
|
||||
}
|
||||
|
@@ -1,8 +1,15 @@
|
||||
<?php
|
||||
/**
|
||||
* @author Alex Bilbie <hello@alexbilbie.com>
|
||||
* @copyright Copyright (c) Alex Bilbie
|
||||
* @license http://mit-license.org/
|
||||
*
|
||||
* @link https://github.com/thephpleague/oauth2-server
|
||||
*/
|
||||
|
||||
namespace OAuth2ServerExamples\Repositories;
|
||||
|
||||
use League\OAuth2\Server\Entities\Interfaces\ClientEntityInterface;
|
||||
use League\OAuth2\Server\Entities\ClientEntityInterface;
|
||||
use League\OAuth2\Server\Repositories\ScopeRepositoryInterface;
|
||||
use OAuth2ServerExamples\Entities\ScopeEntity;
|
||||
|
||||
@@ -41,6 +48,13 @@ class ScopeRepository implements ScopeRepositoryInterface
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
@@ -1,10 +1,16 @@
|
||||
<?php
|
||||
/**
|
||||
* @author Alex Bilbie <hello@alexbilbie.com>
|
||||
* @copyright Copyright (c) Alex Bilbie
|
||||
* @license http://mit-license.org/
|
||||
*
|
||||
* @link https://github.com/thephpleague/oauth2-server
|
||||
*/
|
||||
|
||||
namespace OAuth2ServerExamples\Repositories;
|
||||
|
||||
use League\OAuth2\Server\Entities\Interfaces\ClientEntityInterface;
|
||||
use League\OAuth2\Server\Entities\ClientEntityInterface;
|
||||
use League\OAuth2\Server\Repositories\UserRepositoryInterface;
|
||||
use OAuth2ServerExamples\Entities\ScopeEntity;
|
||||
use OAuth2ServerExamples\Entities\UserEntity;
|
||||
|
||||
class UserRepository implements UserRepositoryInterface
|
||||
@@ -19,10 +25,6 @@ class UserRepository implements UserRepositoryInterface
|
||||
ClientEntityInterface $clientEntity
|
||||
) {
|
||||
if ($username === 'alex' && $password === 'whisky') {
|
||||
$scope = new ScopeEntity();
|
||||
$scope->setIdentifier('email');
|
||||
$scopes[] = $scope;
|
||||
|
||||
return new UserEntity();
|
||||
}
|
||||
|
||||
|
206
src/AuthorizationServer.php
Normal file
206
src/AuthorizationServer.php
Normal file
@@ -0,0 +1,206 @@
|
||||
<?php
|
||||
/**
|
||||
* @author Alex Bilbie <hello@alexbilbie.com>
|
||||
* @copyright Copyright (c) Alex Bilbie
|
||||
* @license http://mit-license.org/
|
||||
*
|
||||
* @link https://github.com/thephpleague/oauth2-server
|
||||
*/
|
||||
|
||||
namespace League\OAuth2\Server;
|
||||
|
||||
use League\Event\EmitterAwareInterface;
|
||||
use League\Event\EmitterAwareTrait;
|
||||
use League\OAuth2\Server\Exception\OAuthServerException;
|
||||
use League\OAuth2\Server\Grant\GrantTypeInterface;
|
||||
use League\OAuth2\Server\Repositories\AccessTokenRepositoryInterface;
|
||||
use League\OAuth2\Server\Repositories\ClientRepositoryInterface;
|
||||
use League\OAuth2\Server\Repositories\ScopeRepositoryInterface;
|
||||
use League\OAuth2\Server\RequestTypes\AuthorizationRequest;
|
||||
use League\OAuth2\Server\ResponseTypes\BearerTokenResponse;
|
||||
use League\OAuth2\Server\ResponseTypes\ResponseTypeInterface;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
use Psr\Http\Message\ServerRequestInterface;
|
||||
|
||||
class AuthorizationServer implements EmitterAwareInterface
|
||||
{
|
||||
use EmitterAwareTrait;
|
||||
|
||||
/**
|
||||
* @var GrantTypeInterface[]
|
||||
*/
|
||||
protected $enabledGrantTypes = [];
|
||||
|
||||
/**
|
||||
* @var \DateInterval[]
|
||||
*/
|
||||
protected $grantTypeAccessTokenTTL = [];
|
||||
|
||||
/**
|
||||
* @var CryptKey
|
||||
*/
|
||||
protected $privateKey;
|
||||
|
||||
/**
|
||||
* @var CryptKey
|
||||
*/
|
||||
protected $publicKey;
|
||||
|
||||
/**
|
||||
* @var null|ResponseTypeInterface
|
||||
*/
|
||||
protected $responseType;
|
||||
|
||||
/**
|
||||
* @var ClientRepositoryInterface
|
||||
*/
|
||||
private $clientRepository;
|
||||
|
||||
/**
|
||||
* @var AccessTokenRepositoryInterface
|
||||
*/
|
||||
private $accessTokenRepository;
|
||||
|
||||
/**
|
||||
* @var ScopeRepositoryInterface
|
||||
*/
|
||||
private $scopeRepository;
|
||||
|
||||
/**
|
||||
* New server instance.
|
||||
*
|
||||
* @param ClientRepositoryInterface $clientRepository
|
||||
* @param AccessTokenRepositoryInterface $accessTokenRepository
|
||||
* @param ScopeRepositoryInterface $scopeRepository
|
||||
* @param CryptKey|string $privateKey
|
||||
* @param CryptKey|string $publicKey
|
||||
* @param null|ResponseTypeInterface $responseType
|
||||
*/
|
||||
public function __construct(
|
||||
ClientRepositoryInterface $clientRepository,
|
||||
AccessTokenRepositoryInterface $accessTokenRepository,
|
||||
ScopeRepositoryInterface $scopeRepository,
|
||||
$privateKey,
|
||||
$publicKey,
|
||||
ResponseTypeInterface $responseType = null
|
||||
) {
|
||||
$this->clientRepository = $clientRepository;
|
||||
$this->accessTokenRepository = $accessTokenRepository;
|
||||
$this->scopeRepository = $scopeRepository;
|
||||
|
||||
if ($privateKey instanceof CryptKey === false) {
|
||||
$privateKey = new CryptKey($privateKey);
|
||||
}
|
||||
$this->privateKey = $privateKey;
|
||||
|
||||
if ($publicKey instanceof CryptKey === false) {
|
||||
$publicKey = new CryptKey($publicKey);
|
||||
}
|
||||
$this->publicKey = $publicKey;
|
||||
|
||||
$this->responseType = $responseType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable a grant type on the server.
|
||||
*
|
||||
* @param GrantTypeInterface $grantType
|
||||
* @param null|\DateInterval $accessTokenTTL
|
||||
*/
|
||||
public function enableGrantType(GrantTypeInterface $grantType, \DateInterval $accessTokenTTL = null)
|
||||
{
|
||||
if ($accessTokenTTL instanceof \DateInterval === false) {
|
||||
$accessTokenTTL = new \DateInterval('PT1H');
|
||||
}
|
||||
|
||||
$grantType->setAccessTokenRepository($this->accessTokenRepository);
|
||||
$grantType->setClientRepository($this->clientRepository);
|
||||
$grantType->setScopeRepository($this->scopeRepository);
|
||||
$grantType->setPrivateKey($this->privateKey);
|
||||
$grantType->setPublicKey($this->publicKey);
|
||||
$grantType->setEmitter($this->getEmitter());
|
||||
|
||||
$this->enabledGrantTypes[$grantType->getIdentifier()] = $grantType;
|
||||
$this->grantTypeAccessTokenTTL[$grantType->getIdentifier()] = $accessTokenTTL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate an authorization request
|
||||
*
|
||||
* @param ServerRequestInterface $request
|
||||
*
|
||||
* @throws OAuthServerException
|
||||
*
|
||||
* @return AuthorizationRequest
|
||||
*/
|
||||
public function validateAuthorizationRequest(ServerRequestInterface $request)
|
||||
{
|
||||
foreach ($this->enabledGrantTypes as $grantType) {
|
||||
if ($grantType->canRespondToAuthorizationRequest($request)) {
|
||||
return $grantType->validateAuthorizationRequest($request);
|
||||
}
|
||||
}
|
||||
|
||||
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)) {
|
||||
$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()
|
||||
{
|
||||
if ($this->responseType instanceof ResponseTypeInterface === false) {
|
||||
$this->responseType = new BearerTokenResponse();
|
||||
}
|
||||
|
||||
$this->responseType->setPrivateKey($this->privateKey);
|
||||
|
||||
return $this->responseType;
|
||||
}
|
||||
}
|
@@ -1,4 +1,11 @@
|
||||
<?php
|
||||
/**
|
||||
* @author Alex Bilbie <hello@alexbilbie.com>
|
||||
* @copyright Copyright (c) Alex Bilbie
|
||||
* @license http://mit-license.org/
|
||||
*
|
||||
* @link https://github.com/thephpleague/oauth2-server
|
||||
*/
|
||||
|
||||
namespace League\OAuth2\Server\AuthorizationValidators;
|
||||
|
||||
|
@@ -1,9 +1,17 @@
|
||||
<?php
|
||||
/**
|
||||
* @author Alex Bilbie <hello@alexbilbie.com>
|
||||
* @copyright Copyright (c) Alex Bilbie
|
||||
* @license http://mit-license.org/
|
||||
*
|
||||
* @link https://github.com/thephpleague/oauth2-server
|
||||
*/
|
||||
|
||||
namespace League\OAuth2\Server\AuthorizationValidators;
|
||||
|
||||
use Lcobucci\JWT\Parser;
|
||||
use Lcobucci\JWT\Signer\Rsa\Sha256;
|
||||
use Lcobucci\JWT\ValidationData;
|
||||
use League\OAuth2\Server\CryptTrait;
|
||||
use League\OAuth2\Server\Exception\OAuthServerException;
|
||||
use League\OAuth2\Server\Repositories\AccessTokenRepositoryInterface;
|
||||
@@ -14,14 +22,12 @@ class BearerTokenValidator implements AuthorizationValidatorInterface
|
||||
use CryptTrait;
|
||||
|
||||
/**
|
||||
* @var \League\OAuth2\Server\Repositories\AccessTokenRepositoryInterface
|
||||
* @var AccessTokenRepositoryInterface
|
||||
*/
|
||||
private $accessTokenRepository;
|
||||
|
||||
/**
|
||||
* BearerTokenValidator constructor.
|
||||
*
|
||||
* @param \League\OAuth2\Server\Repositories\AccessTokenRepositoryInterface $accessTokenRepository
|
||||
* @param AccessTokenRepositoryInterface $accessTokenRepository
|
||||
*/
|
||||
public function __construct(AccessTokenRepositoryInterface $accessTokenRepository)
|
||||
{
|
||||
@@ -43,10 +49,18 @@ class BearerTokenValidator implements AuthorizationValidatorInterface
|
||||
try {
|
||||
// Attempt to parse and validate the JWT
|
||||
$token = (new Parser())->parse($jwt);
|
||||
if ($token->verify(new Sha256(), $this->publicKeyPath) === false) {
|
||||
if ($token->verify(new Sha256(), $this->publicKey->getKeyPath()) === false) {
|
||||
throw OAuthServerException::accessDenied('Access token could not be verified');
|
||||
}
|
||||
|
||||
// Ensure access token hasn't expired
|
||||
$data = new ValidationData();
|
||||
$data->setCurrentTime(time());
|
||||
|
||||
if ($token->validate($data) === false) {
|
||||
throw OAuthServerException::accessDenied('Access token is invalid');
|
||||
}
|
||||
|
||||
// Check if token has been revoked
|
||||
if ($this->accessTokenRepository->isAccessTokenRevoked($token->getClaim('jti'))) {
|
||||
throw OAuthServerException::accessDenied('Access token has been revoked');
|
||||
@@ -61,6 +75,9 @@ class BearerTokenValidator implements AuthorizationValidatorInterface
|
||||
} catch (\InvalidArgumentException $exception) {
|
||||
// JWT couldn't be parsed so return the request as is
|
||||
throw OAuthServerException::accessDenied($exception->getMessage());
|
||||
} catch (\RuntimeException $exception) {
|
||||
//JWR couldn't be parsed so return the request as is
|
||||
throw OAuthServerException::accessDenied('Error while decoding to JSON');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
92
src/CryptKey.php
Normal file
92
src/CryptKey.php
Normal file
@@ -0,0 +1,92 @@
|
||||
<?php
|
||||
/**
|
||||
* Cryptography key holder.
|
||||
*
|
||||
* @author Julián Gutiérrez <juliangut@gmail.com>
|
||||
* @copyright Copyright (c) Alex Bilbie
|
||||
* @license http://mit-license.org/
|
||||
*
|
||||
* @link https://github.com/thephpleague/oauth2-server
|
||||
*/
|
||||
|
||||
namespace League\OAuth2\Server;
|
||||
|
||||
class CryptKey
|
||||
{
|
||||
const RSA_KEY_PATTERN =
|
||||
'/^(-----BEGIN (RSA )?(PUBLIC|PRIVATE) KEY-----\n)(.|\n)+(-----END (RSA )?(PUBLIC|PRIVATE) KEY-----)$/';
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $keyPath;
|
||||
|
||||
/**
|
||||
* @var null|string
|
||||
*/
|
||||
protected $passPhrase;
|
||||
|
||||
/**
|
||||
* @param string $keyPath
|
||||
* @param null|string $passPhrase
|
||||
*/
|
||||
public function __construct($keyPath, $passPhrase = null)
|
||||
{
|
||||
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));
|
||||
}
|
||||
|
||||
$this->keyPath = $keyPath;
|
||||
$this->passPhrase = $passPhrase;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $key
|
||||
*
|
||||
* @throws \RuntimeException
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private function saveKeyToFile($key)
|
||||
{
|
||||
$keyPath = sys_get_temp_dir() . '/' . sha1($key) . '.key';
|
||||
|
||||
if (!file_exists($keyPath) && !touch($keyPath)) {
|
||||
// @codeCoverageIgnoreStart
|
||||
throw new \RuntimeException('"%s" key file could not be created', $keyPath);
|
||||
// @codeCoverageIgnoreEnd
|
||||
}
|
||||
|
||||
file_put_contents($keyPath, $key);
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
@@ -8,46 +8,39 @@
|
||||
*
|
||||
* @link https://github.com/thephpleague/oauth2-server
|
||||
*/
|
||||
|
||||
namespace League\OAuth2\Server;
|
||||
|
||||
trait CryptTrait
|
||||
{
|
||||
/**
|
||||
* @var string
|
||||
* @var CryptKey
|
||||
*/
|
||||
protected $privateKeyPath;
|
||||
protected $privateKey;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
* @var CryptKey
|
||||
*/
|
||||
protected $publicKeyPath;
|
||||
protected $publicKey;
|
||||
|
||||
/**
|
||||
* Set path to private key.
|
||||
*
|
||||
* @param string $privateKeyPath
|
||||
* @param CryptKey $privateKey
|
||||
*/
|
||||
public function setPrivateKeyPath($privateKeyPath)
|
||||
public function setPrivateKey(CryptKey $privateKey)
|
||||
{
|
||||
if (strpos($privateKeyPath, 'file://') !== 0) {
|
||||
$privateKeyPath = 'file://' . $privateKeyPath;
|
||||
}
|
||||
|
||||
$this->privateKeyPath = $privateKeyPath;
|
||||
$this->privateKey = $privateKey;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set path to public key.
|
||||
*
|
||||
* @param string $publicKeyPath
|
||||
* @param CryptKey $publicKey
|
||||
*/
|
||||
public function setPublicKeyPath($publicKeyPath)
|
||||
public function setPublicKey(CryptKey $publicKey)
|
||||
{
|
||||
if (strpos($publicKeyPath, 'file://') !== 0) {
|
||||
$publicKeyPath = 'file://' . $publicKeyPath;
|
||||
}
|
||||
|
||||
$this->publicKeyPath = $publicKeyPath;
|
||||
$this->publicKey = $publicKey;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -55,14 +48,18 @@ trait CryptTrait
|
||||
*
|
||||
* @param string $unencryptedData
|
||||
*
|
||||
* @throws \LogicException
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function encrypt($unencryptedData)
|
||||
{
|
||||
$privateKey = openssl_pkey_get_private($this->privateKeyPath);
|
||||
$privateKey = openssl_pkey_get_private($this->privateKey->getKeyPath(), $this->privateKey->getPassPhrase());
|
||||
$privateKeyDetails = @openssl_pkey_get_details($privateKey);
|
||||
if ($privateKeyDetails === null) {
|
||||
throw new \LogicException(sprintf('Could not get details of private key: %s', $this->privateKeyPath));
|
||||
throw new \LogicException(
|
||||
sprintf('Could not get details of private key: %s', $this->privateKey->getKeyPath())
|
||||
);
|
||||
}
|
||||
|
||||
$chunkSize = ceil($privateKeyDetails['bits'] / 8) - 11;
|
||||
@@ -78,7 +75,7 @@ trait CryptTrait
|
||||
}
|
||||
$output .= $encrypted;
|
||||
}
|
||||
openssl_free_key($privateKey);
|
||||
openssl_pkey_free($privateKey);
|
||||
|
||||
return base64_encode($output);
|
||||
}
|
||||
@@ -94,10 +91,12 @@ trait CryptTrait
|
||||
*/
|
||||
protected function decrypt($encryptedData)
|
||||
{
|
||||
$publicKey = openssl_pkey_get_public($this->publicKeyPath);
|
||||
$publicKey = openssl_pkey_get_public($this->publicKey->getKeyPath());
|
||||
$publicKeyDetails = @openssl_pkey_get_details($publicKey);
|
||||
if ($publicKeyDetails === null) {
|
||||
throw new \LogicException(sprintf('Could not get details of public key: %s', $this->publicKeyPath));
|
||||
throw new \LogicException(
|
||||
sprintf('Could not get details of public key: %s', $this->publicKey->getKeyPath())
|
||||
);
|
||||
}
|
||||
|
||||
$chunkSize = ceil($publicKeyDetails['bits'] / 8);
|
||||
@@ -115,7 +114,7 @@ trait CryptTrait
|
||||
}
|
||||
$output .= $decrypted;
|
||||
}
|
||||
openssl_free_key($publicKey);
|
||||
openssl_pkey_free($publicKey);
|
||||
|
||||
return $output;
|
||||
}
|
||||
|
@@ -1,36 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace League\OAuth2\Server\Entities;
|
||||
|
||||
use Lcobucci\JWT\Builder;
|
||||
use Lcobucci\JWT\Signer\Key;
|
||||
use Lcobucci\JWT\Signer\Rsa\Sha256;
|
||||
use League\OAuth2\Server\Entities\Interfaces\AccessTokenEntityInterface;
|
||||
use League\OAuth2\Server\Entities\Traits\EntityTrait;
|
||||
use League\OAuth2\Server\Entities\Traits\TokenEntityTrait;
|
||||
|
||||
class AccessTokenEntity implements AccessTokenEntityInterface
|
||||
{
|
||||
use EntityTrait, TokenEntityTrait;
|
||||
|
||||
/**
|
||||
* Generate a JWT from the access token
|
||||
*
|
||||
* @param string $privateKeyPath
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function convertToJWT($privateKeyPath)
|
||||
{
|
||||
return (new Builder())
|
||||
->setAudience($this->getClient()->getIdentifier())
|
||||
->setId($this->getIdentifier(), true)
|
||||
->setIssuedAt(time())
|
||||
->setNotBefore(time())
|
||||
->setExpiration($this->getExpiryDateTime()->getTimestamp())
|
||||
->setSubject($this->getUserIdentifier())
|
||||
->set('scopes', $this->getScopes())
|
||||
->sign(new Sha256(), new Key($privateKeyPath))
|
||||
->getToken();
|
||||
}
|
||||
}
|
24
src/Entities/AccessTokenEntityInterface.php
Normal file
24
src/Entities/AccessTokenEntityInterface.php
Normal file
@@ -0,0 +1,24 @@
|
||||
<?php
|
||||
/**
|
||||
* @author Alex Bilbie <hello@alexbilbie.com>
|
||||
* @copyright Copyright (c) Alex Bilbie
|
||||
* @license http://mit-license.org/
|
||||
*
|
||||
* @link https://github.com/thephpleague/oauth2-server
|
||||
*/
|
||||
|
||||
namespace League\OAuth2\Server\Entities;
|
||||
|
||||
use League\OAuth2\Server\CryptKey;
|
||||
|
||||
interface AccessTokenEntityInterface extends TokenInterface
|
||||
{
|
||||
/**
|
||||
* Generate a JWT from the access token
|
||||
*
|
||||
* @param CryptKey $privateKey
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function convertToJWT(CryptKey $privateKey);
|
||||
}
|
@@ -1,33 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace League\OAuth2\Server\Entities;
|
||||
|
||||
use League\OAuth2\Server\Entities\Interfaces\AuthCodeEntityInterface;
|
||||
use League\OAuth2\Server\Entities\Traits\EntityTrait;
|
||||
use League\OAuth2\Server\Entities\Traits\TokenEntityTrait;
|
||||
|
||||
/**
|
||||
* Class AuthCodeEntity.
|
||||
*/
|
||||
class AuthCodeEntity implements AuthCodeEntityInterface
|
||||
{
|
||||
use EntityTrait, TokenEntityTrait;
|
||||
|
||||
protected $redirectUri;
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getRedirectUri()
|
||||
{
|
||||
return $this->redirectUri;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $uri
|
||||
*/
|
||||
public function setRedirectUri($uri)
|
||||
{
|
||||
$this->redirectUri = $uri;
|
||||
}
|
||||
}
|
23
src/Entities/AuthCodeEntityInterface.php
Normal file
23
src/Entities/AuthCodeEntityInterface.php
Normal file
@@ -0,0 +1,23 @@
|
||||
<?php
|
||||
/**
|
||||
* @author Alex Bilbie <hello@alexbilbie.com>
|
||||
* @copyright Copyright (c) Alex Bilbie
|
||||
* @license http://mit-license.org/
|
||||
*
|
||||
* @link https://github.com/thephpleague/oauth2-server
|
||||
*/
|
||||
|
||||
namespace League\OAuth2\Server\Entities;
|
||||
|
||||
interface AuthCodeEntityInterface extends TokenInterface
|
||||
{
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getRedirectUri();
|
||||
|
||||
/**
|
||||
* @param string $uri
|
||||
*/
|
||||
public function setRedirectUri($uri);
|
||||
}
|
36
src/Entities/ClientEntityInterface.php
Normal file
36
src/Entities/ClientEntityInterface.php
Normal file
@@ -0,0 +1,36 @@
|
||||
<?php
|
||||
/**
|
||||
* @author Alex Bilbie <hello@alexbilbie.com>
|
||||
* @copyright Copyright (c) Alex Bilbie
|
||||
* @license http://mit-license.org/
|
||||
*
|
||||
* @link https://github.com/thephpleague/oauth2-server
|
||||
*/
|
||||
|
||||
namespace League\OAuth2\Server\Entities;
|
||||
|
||||
interface ClientEntityInterface
|
||||
{
|
||||
/**
|
||||
* Get the client's identifier.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getIdentifier();
|
||||
|
||||
/**
|
||||
* Get the client's name.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getName();
|
||||
|
||||
/**
|
||||
* Returns the registered redirect URI (as a string).
|
||||
*
|
||||
* Alternatively return an indexed array of redirect URIs.
|
||||
*
|
||||
* @return string|string[]
|
||||
*/
|
||||
public function getRedirectUri();
|
||||
}
|
@@ -1,15 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace League\OAuth2\Server\Entities\Interfaces;
|
||||
|
||||
interface AccessTokenEntityInterface extends TokenInterface
|
||||
{
|
||||
/**
|
||||
* Generate a JWT from the access token
|
||||
*
|
||||
* @param string $privateKeyPath
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function convertToJWT($privateKeyPath);
|
||||
}
|
@@ -1,16 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace League\OAuth2\Server\Entities\Interfaces;
|
||||
|
||||
interface AuthCodeEntityInterface extends TokenInterface
|
||||
{
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getRedirectUri();
|
||||
|
||||
/**
|
||||
* @param string $uri
|
||||
*/
|
||||
public function setRedirectUri($uri);
|
||||
}
|
@@ -1,48 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace League\OAuth2\Server\Entities\Interfaces;
|
||||
|
||||
interface ClientEntityInterface
|
||||
{
|
||||
/**
|
||||
* Get the client's identifier.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getIdentifier();
|
||||
|
||||
/**
|
||||
* Set the client's identifier.
|
||||
*
|
||||
* @param $identifier
|
||||
*/
|
||||
public function setIdentifier($identifier);
|
||||
|
||||
/**
|
||||
* Get the client's name.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getName();
|
||||
|
||||
/**
|
||||
* Set the client's name.
|
||||
*
|
||||
* @param string $name
|
||||
*/
|
||||
public function setName($name);
|
||||
|
||||
/**
|
||||
* Set the client's redirect uri.
|
||||
*
|
||||
* @param string $redirectUri
|
||||
*/
|
||||
public function setRedirectUri($redirectUri);
|
||||
|
||||
/**
|
||||
* Returns the registered redirect URI.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getRedirectUri();
|
||||
}
|
@@ -1,20 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace League\OAuth2\Server\Entities\Interfaces;
|
||||
|
||||
interface ScopeEntityInterface extends \JsonSerializable
|
||||
{
|
||||
/**
|
||||
* Get the scope's identifier.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getIdentifier();
|
||||
|
||||
/**
|
||||
* Set the scope's identifier.
|
||||
*
|
||||
* @param $identifier
|
||||
*/
|
||||
public function setIdentifier($identifier);
|
||||
}
|
@@ -1,13 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace League\OAuth2\Server\Entities\Interfaces;
|
||||
|
||||
interface UserEntityInterface
|
||||
{
|
||||
/**
|
||||
* Return the user's identifier.
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function getIdentifier();
|
||||
}
|
@@ -1,15 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace League\OAuth2\Server\Entities;
|
||||
|
||||
use League\OAuth2\Server\Entities\Interfaces\RefreshTokenEntityInterface;
|
||||
use League\OAuth2\Server\Entities\Traits\EntityTrait;
|
||||
use League\OAuth2\Server\Entities\Traits\RefreshTokenTrait;
|
||||
|
||||
/**
|
||||
* Class RefreshTokenEntity.
|
||||
*/
|
||||
class RefreshTokenEntity implements RefreshTokenEntityInterface
|
||||
{
|
||||
use EntityTrait, RefreshTokenTrait;
|
||||
}
|
@@ -1,6 +1,13 @@
|
||||
<?php
|
||||
/**
|
||||
* @author Alex Bilbie <hello@alexbilbie.com>
|
||||
* @copyright Copyright (c) Alex Bilbie
|
||||
* @license http://mit-license.org/
|
||||
*
|
||||
* @link https://github.com/thephpleague/oauth2-server
|
||||
*/
|
||||
|
||||
namespace League\OAuth2\Server\Entities\Interfaces;
|
||||
namespace League\OAuth2\Server\Entities;
|
||||
|
||||
interface RefreshTokenEntityInterface
|
||||
{
|
||||
@@ -35,21 +42,14 @@ interface RefreshTokenEntityInterface
|
||||
/**
|
||||
* Set the access token that the refresh token was associated with.
|
||||
*
|
||||
* @param \League\OAuth2\Server\Entities\Interfaces\AccessTokenEntityInterface $accessToken
|
||||
* @param AccessTokenEntityInterface $accessToken
|
||||
*/
|
||||
public function setAccessToken(AccessTokenEntityInterface $accessToken);
|
||||
|
||||
/**
|
||||
* Get the access token that the refresh token was originally associated with.
|
||||
*
|
||||
* @return \League\OAuth2\Server\Entities\Interfaces\AccessTokenEntityInterface
|
||||
* @return AccessTokenEntityInterface
|
||||
*/
|
||||
public function getAccessToken();
|
||||
|
||||
/**
|
||||
* Has the token expired?
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isExpired();
|
||||
}
|
20
src/Entities/ScopeEntityInterface.php
Normal file
20
src/Entities/ScopeEntityInterface.php
Normal file
@@ -0,0 +1,20 @@
|
||||
<?php
|
||||
/**
|
||||
* @author Alex Bilbie <hello@alexbilbie.com>
|
||||
* @copyright Copyright (c) Alex Bilbie
|
||||
* @license http://mit-license.org/
|
||||
*
|
||||
* @link https://github.com/thephpleague/oauth2-server
|
||||
*/
|
||||
|
||||
namespace League\OAuth2\Server\Entities;
|
||||
|
||||
interface ScopeEntityInterface extends \JsonSerializable
|
||||
{
|
||||
/**
|
||||
* Get the scope's identifier.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getIdentifier();
|
||||
}
|
@@ -1,6 +1,13 @@
|
||||
<?php
|
||||
/**
|
||||
* @author Alex Bilbie <hello@alexbilbie.com>
|
||||
* @copyright Copyright (c) Alex Bilbie
|
||||
* @license http://mit-license.org/
|
||||
*
|
||||
* @link https://github.com/thephpleague/oauth2-server
|
||||
*/
|
||||
|
||||
namespace League\OAuth2\Server\Entities\Interfaces;
|
||||
namespace League\OAuth2\Server\Entities;
|
||||
|
||||
interface TokenInterface
|
||||
{
|
||||
@@ -56,14 +63,14 @@ interface TokenInterface
|
||||
/**
|
||||
* Set the client that the token was issued to.
|
||||
*
|
||||
* @param \League\OAuth2\Server\Entities\Interfaces\ClientEntityInterface $client
|
||||
* @param ClientEntityInterface $client
|
||||
*/
|
||||
public function setClient(ClientEntityInterface $client);
|
||||
|
||||
/**
|
||||
* Associate a scope with the token.
|
||||
*
|
||||
* @param \League\OAuth2\Server\Entities\Interfaces\ScopeEntityInterface $scope
|
||||
* @param ScopeEntityInterface $scope
|
||||
*/
|
||||
public function addScope(ScopeEntityInterface $scope);
|
||||
|
||||
@@ -73,11 +80,4 @@ interface TokenInterface
|
||||
* @return ScopeEntityInterface[]
|
||||
*/
|
||||
public function getScopes();
|
||||
|
||||
/**
|
||||
* Has the token expired?
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isExpired();
|
||||
}
|
61
src/Entities/Traits/AccessTokenTrait.php
Normal file
61
src/Entities/Traits/AccessTokenTrait.php
Normal file
@@ -0,0 +1,61 @@
|
||||
<?php
|
||||
/**
|
||||
* @author Alex Bilbie <hello@alexbilbie.com>
|
||||
* @copyright Copyright (c) Alex Bilbie
|
||||
* @license http://mit-license.org/
|
||||
*
|
||||
* @link https://github.com/thephpleague/oauth2-server
|
||||
*/
|
||||
|
||||
namespace League\OAuth2\Server\Entities\Traits;
|
||||
|
||||
use Lcobucci\JWT\Builder;
|
||||
use Lcobucci\JWT\Signer\Key;
|
||||
use Lcobucci\JWT\Signer\Rsa\Sha256;
|
||||
use League\OAuth2\Server\CryptKey;
|
||||
use League\OAuth2\Server\Entities\ClientEntityInterface;
|
||||
use League\OAuth2\Server\Entities\ScopeEntityInterface;
|
||||
|
||||
trait AccessTokenTrait
|
||||
{
|
||||
/**
|
||||
* Generate a JWT from the access token
|
||||
*
|
||||
* @param CryptKey $privateKey
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function convertToJWT(CryptKey $privateKey)
|
||||
{
|
||||
return (new Builder())
|
||||
->setAudience($this->getClient()->getIdentifier())
|
||||
->setId($this->getIdentifier(), true)
|
||||
->setIssuedAt(time())
|
||||
->setNotBefore(time())
|
||||
->setExpiration($this->getExpiryDateTime()->getTimestamp())
|
||||
->setSubject($this->getUserIdentifier())
|
||||
->set('scopes', $this->getScopes())
|
||||
->sign(new Sha256(), new Key($privateKey->getKeyPath(), $privateKey->getPassPhrase()))
|
||||
->getToken();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return ClientEntityInterface
|
||||
*/
|
||||
abstract public function getClient();
|
||||
|
||||
/**
|
||||
* @return \DateTime
|
||||
*/
|
||||
abstract public function getExpiryDateTime();
|
||||
|
||||
/**
|
||||
* @return string|int
|
||||
*/
|
||||
abstract public function getUserIdentifier();
|
||||
|
||||
/**
|
||||
* @return ScopeEntityInterface[]
|
||||
*/
|
||||
abstract public function getScopes();
|
||||
}
|
34
src/Entities/Traits/AuthCodeTrait.php
Normal file
34
src/Entities/Traits/AuthCodeTrait.php
Normal file
@@ -0,0 +1,34 @@
|
||||
<?php
|
||||
/**
|
||||
* @author Alex Bilbie <hello@alexbilbie.com>
|
||||
* @copyright Copyright (c) Alex Bilbie
|
||||
* @license http://mit-license.org/
|
||||
*
|
||||
* @link https://github.com/thephpleague/oauth2-server
|
||||
*/
|
||||
|
||||
namespace League\OAuth2\Server\Entities\Traits;
|
||||
|
||||
trait AuthCodeTrait
|
||||
{
|
||||
/**
|
||||
* @var null|string
|
||||
*/
|
||||
protected $redirectUri;
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getRedirectUri()
|
||||
{
|
||||
return $this->redirectUri;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $uri
|
||||
*/
|
||||
public function setRedirectUri($uri)
|
||||
{
|
||||
$this->redirectUri = $uri;
|
||||
}
|
||||
}
|
46
src/Entities/Traits/ClientTrait.php
Normal file
46
src/Entities/Traits/ClientTrait.php
Normal file
@@ -0,0 +1,46 @@
|
||||
<?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;
|
||||
|
||||
/**
|
||||
* 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;
|
||||
}
|
||||
}
|
@@ -1,4 +1,11 @@
|
||||
<?php
|
||||
/**
|
||||
* @author Alex Bilbie <hello@alexbilbie.com>
|
||||
* @copyright Copyright (c) Alex Bilbie
|
||||
* @license http://mit-license.org/
|
||||
*
|
||||
* @link https://github.com/thephpleague/oauth2-server
|
||||
*/
|
||||
|
||||
namespace League\OAuth2\Server\Entities\Traits;
|
||||
|
||||
|
@@ -1,9 +1,15 @@
|
||||
<?php
|
||||
/**
|
||||
* @author Alex Bilbie <hello@alexbilbie.com>
|
||||
* @copyright Copyright (c) Alex Bilbie
|
||||
* @license http://mit-license.org/
|
||||
*
|
||||
* @link https://github.com/thephpleague/oauth2-server
|
||||
*/
|
||||
|
||||
namespace League\OAuth2\Server\Entities\Traits;
|
||||
|
||||
use DateTime;
|
||||
use League\OAuth2\Server\Entities\Interfaces\AccessTokenEntityInterface;
|
||||
use League\OAuth2\Server\Entities\AccessTokenEntityInterface;
|
||||
|
||||
trait RefreshTokenTrait
|
||||
{
|
||||
@@ -13,7 +19,7 @@ trait RefreshTokenTrait
|
||||
protected $accessToken;
|
||||
|
||||
/**
|
||||
* @var DateTime
|
||||
* @var \DateTime
|
||||
*/
|
||||
protected $expiryDateTime;
|
||||
|
||||
@@ -36,7 +42,7 @@ trait RefreshTokenTrait
|
||||
/**
|
||||
* Get the token's expiry date time.
|
||||
*
|
||||
* @return DateTime
|
||||
* @return \DateTime
|
||||
*/
|
||||
public function getExpiryDateTime()
|
||||
{
|
||||
@@ -46,20 +52,10 @@ trait RefreshTokenTrait
|
||||
/**
|
||||
* Set the date time when the token expires.
|
||||
*
|
||||
* @param DateTime $dateTime
|
||||
* @param \DateTime $dateTime
|
||||
*/
|
||||
public function setExpiryDateTime(DateTime $dateTime)
|
||||
public function setExpiryDateTime(\DateTime $dateTime)
|
||||
{
|
||||
$this->expiryDateTime = $dateTime;
|
||||
}
|
||||
|
||||
/**
|
||||
* Has the token expired?
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isExpired()
|
||||
{
|
||||
return (new DateTime()) > $this->getExpiryDateTime();
|
||||
}
|
||||
}
|
||||
|
@@ -1,10 +1,16 @@
|
||||
<?php
|
||||
/**
|
||||
* @author Alex Bilbie <hello@alexbilbie.com>
|
||||
* @copyright Copyright (c) Alex Bilbie
|
||||
* @license http://mit-license.org/
|
||||
*
|
||||
* @link https://github.com/thephpleague/oauth2-server
|
||||
*/
|
||||
|
||||
namespace League\OAuth2\Server\Entities\Traits;
|
||||
|
||||
use DateTime;
|
||||
use League\OAuth2\Server\Entities\Interfaces\ClientEntityInterface;
|
||||
use League\OAuth2\Server\Entities\Interfaces\ScopeEntityInterface;
|
||||
use League\OAuth2\Server\Entities\ClientEntityInterface;
|
||||
use League\OAuth2\Server\Entities\ScopeEntityInterface;
|
||||
|
||||
trait TokenEntityTrait
|
||||
{
|
||||
@@ -14,7 +20,7 @@ trait TokenEntityTrait
|
||||
protected $scopes = [];
|
||||
|
||||
/**
|
||||
* @var DateTime
|
||||
* @var \DateTime
|
||||
*/
|
||||
protected $expiryDateTime;
|
||||
|
||||
@@ -31,7 +37,7 @@ trait TokenEntityTrait
|
||||
/**
|
||||
* Associate a scope with the token.
|
||||
*
|
||||
* @param \League\OAuth2\Server\Entities\Interfaces\ScopeEntityInterface $scope
|
||||
* @param ScopeEntityInterface $scope
|
||||
*/
|
||||
public function addScope(ScopeEntityInterface $scope)
|
||||
{
|
||||
@@ -51,7 +57,7 @@ trait TokenEntityTrait
|
||||
/**
|
||||
* Get the token's expiry date time.
|
||||
*
|
||||
* @return DateTime
|
||||
* @return \DateTime
|
||||
*/
|
||||
public function getExpiryDateTime()
|
||||
{
|
||||
@@ -61,9 +67,9 @@ trait TokenEntityTrait
|
||||
/**
|
||||
* Set the date time when the token expires.
|
||||
*
|
||||
* @param DateTime $dateTime
|
||||
* @param \DateTime $dateTime
|
||||
*/
|
||||
public function setExpiryDateTime(DateTime $dateTime)
|
||||
public function setExpiryDateTime(\DateTime $dateTime)
|
||||
{
|
||||
$this->expiryDateTime = $dateTime;
|
||||
}
|
||||
@@ -101,20 +107,10 @@ trait TokenEntityTrait
|
||||
/**
|
||||
* Set the client that the token was issued to.
|
||||
*
|
||||
* @param \League\OAuth2\Server\Entities\Interfaces\ClientEntityInterface $client
|
||||
* @param ClientEntityInterface $client
|
||||
*/
|
||||
public function setClient(ClientEntityInterface $client)
|
||||
{
|
||||
$this->client = $client;
|
||||
}
|
||||
|
||||
/**
|
||||
* Has the token expired?
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isExpired()
|
||||
{
|
||||
return (new DateTime()) > $this->getExpiryDateTime();
|
||||
}
|
||||
}
|
||||
|
20
src/Entities/UserEntityInterface.php
Normal file
20
src/Entities/UserEntityInterface.php
Normal 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();
|
||||
}
|
@@ -1,4 +1,11 @@
|
||||
<?php
|
||||
/**
|
||||
* @author Alex Bilbie <hello@alexbilbie.com>
|
||||
* @copyright Copyright (c) Alex Bilbie
|
||||
* @license http://mit-license.org/
|
||||
*
|
||||
* @link https://github.com/thephpleague/oauth2-server
|
||||
*/
|
||||
|
||||
namespace League\OAuth2\Server\Exception;
|
||||
|
||||
@@ -62,7 +69,7 @@ class OAuthServerException extends \Exception
|
||||
* Invalid request error.
|
||||
*
|
||||
* @param string $parameter The invalid parameter
|
||||
* @param string|null $hint
|
||||
* @param null|string $hint
|
||||
*
|
||||
* @return static
|
||||
*/
|
||||
@@ -119,6 +126,8 @@ class OAuthServerException extends \Exception
|
||||
* @param $hint
|
||||
*
|
||||
* @return static
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public static function serverError($hint)
|
||||
{
|
||||
@@ -134,7 +143,7 @@ class OAuthServerException extends \Exception
|
||||
/**
|
||||
* Invalid refresh token.
|
||||
*
|
||||
* @param string|null $hint
|
||||
* @param null|string $hint
|
||||
*
|
||||
* @return static
|
||||
*/
|
||||
@@ -146,8 +155,8 @@ class OAuthServerException extends \Exception
|
||||
/**
|
||||
* Access denied.
|
||||
*
|
||||
* @param string|null $hint
|
||||
* @param string|null $redirectUri
|
||||
* @param null|string $hint
|
||||
* @param null|string $redirectUri
|
||||
*
|
||||
* @return static
|
||||
*/
|
||||
@@ -163,6 +172,26 @@ class OAuthServerException extends \Exception
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
@@ -174,11 +203,10 @@ class OAuthServerException extends \Exception
|
||||
/**
|
||||
* Generate a HTTP response.
|
||||
*
|
||||
* @param \Psr\Http\Message\ResponseInterface $response
|
||||
* @param bool $useFragment True if errors should be in the URI fragment instead of
|
||||
* query string
|
||||
* @param ResponseInterface $response
|
||||
* @param bool $useFragment True if errors should be in the URI fragment instead of query string
|
||||
*
|
||||
* @return \Psr\Http\Message\ResponseInterface
|
||||
* @return ResponseInterface
|
||||
*/
|
||||
public function generateHttpResponse(ResponseInterface $response, $useFragment = false)
|
||||
{
|
||||
@@ -239,7 +267,7 @@ class OAuthServerException extends \Exception
|
||||
) {
|
||||
$authScheme = 'Bearer';
|
||||
}
|
||||
$headers[] = 'WWW-Authenticate: ' . $authScheme . ' realm="OAuth"';
|
||||
$headers['WWW-Authenticate'] = $authScheme . ' realm="OAuth"';
|
||||
}
|
||||
// @codeCoverageIgnoreEnd
|
||||
return $headers;
|
||||
|
@@ -0,0 +1,20 @@
|
||||
<?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
|
||||
{
|
||||
public static function create()
|
||||
{
|
||||
$errorMessage = 'Could not create unique access token identifier';
|
||||
|
||||
return new static($errorMessage, 100, 'access_token_duplicate', 500);
|
||||
}
|
||||
}
|
@@ -11,45 +11,8 @@
|
||||
|
||||
namespace League\OAuth2\Server\Grant;
|
||||
|
||||
use League\OAuth2\Server\TemplateRenderer\PlatesRenderer;
|
||||
use League\OAuth2\Server\TemplateRenderer\RendererInterface;
|
||||
use League\Plates\Engine;
|
||||
|
||||
abstract class AbstractAuthorizeGrant extends AbstractGrant
|
||||
{
|
||||
/**
|
||||
* @var \League\OAuth2\Server\TemplateRenderer\RendererInterface
|
||||
*/
|
||||
protected $templateRenderer;
|
||||
|
||||
/**
|
||||
* Set the template renderer
|
||||
*
|
||||
* @param RendererInterface $templateRenderer
|
||||
*/
|
||||
public function setTemplateRenderer(RendererInterface $templateRenderer)
|
||||
{
|
||||
$this->templateRenderer = $templateRenderer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve template renderer.
|
||||
*
|
||||
* @return \League\OAuth2\Server\TemplateRenderer\RendererInterface
|
||||
*/
|
||||
protected function getTemplateRenderer()
|
||||
{
|
||||
if (!$this->templateRenderer instanceof RendererInterface) {
|
||||
$this->templateRenderer = new PlatesRenderer(
|
||||
new Engine(__DIR__ . '/../TemplateRenderer/DefaultTemplates'),
|
||||
'login_user',
|
||||
'authorize_client'
|
||||
);
|
||||
}
|
||||
|
||||
return $this->templateRenderer;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $uri
|
||||
* @param array $params
|
||||
|
@@ -12,13 +12,13 @@ namespace League\OAuth2\Server\Grant;
|
||||
|
||||
use League\Event\EmitterAwareTrait;
|
||||
use League\OAuth2\Server\CryptTrait;
|
||||
use League\OAuth2\Server\Entities\AccessTokenEntity;
|
||||
use League\OAuth2\Server\Entities\AuthCodeEntity;
|
||||
use League\OAuth2\Server\Entities\Interfaces\AccessTokenEntityInterface;
|
||||
use League\OAuth2\Server\Entities\Interfaces\ClientEntityInterface;
|
||||
use League\OAuth2\Server\Entities\Interfaces\ScopeEntityInterface;
|
||||
use League\OAuth2\Server\Entities\RefreshTokenEntity;
|
||||
use League\OAuth2\Server\Entities\AccessTokenEntityInterface;
|
||||
use League\OAuth2\Server\Entities\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;
|
||||
@@ -26,6 +26,7 @@ use League\OAuth2\Server\Repositories\RefreshTokenRepositoryInterface;
|
||||
use League\OAuth2\Server\Repositories\ScopeRepositoryInterface;
|
||||
use League\OAuth2\Server\Repositories\UserRepositoryInterface;
|
||||
use League\OAuth2\Server\RequestEvent;
|
||||
use League\OAuth2\Server\RequestTypes\AuthorizationRequest;
|
||||
use Psr\Http\Message\ServerRequestInterface;
|
||||
|
||||
/**
|
||||
@@ -37,10 +38,7 @@ abstract class AbstractGrant implements GrantTypeInterface
|
||||
|
||||
const SCOPE_DELIMITER_STRING = ' ';
|
||||
|
||||
/**
|
||||
* @var ServerRequestInterface
|
||||
*/
|
||||
protected $request;
|
||||
const MAX_RANDOM_TOKEN_GENERATION_ATTEMPTS = 10;
|
||||
|
||||
/**
|
||||
* @var ClientRepositoryInterface
|
||||
@@ -58,17 +56,17 @@ abstract class AbstractGrant implements GrantTypeInterface
|
||||
protected $scopeRepository;
|
||||
|
||||
/**
|
||||
* @var \League\OAuth2\Server\Repositories\AuthCodeRepositoryInterface
|
||||
* @var AuthCodeRepositoryInterface
|
||||
*/
|
||||
protected $authCodeRepository;
|
||||
|
||||
/**
|
||||
* @var \League\OAuth2\Server\Repositories\RefreshTokenRepositoryInterface
|
||||
* @var RefreshTokenRepositoryInterface
|
||||
*/
|
||||
protected $refreshTokenRepository;
|
||||
|
||||
/**
|
||||
* @var \League\OAuth2\Server\Repositories\UserRepositoryInterface
|
||||
* @var UserRepositoryInterface
|
||||
*/
|
||||
protected $userRepository;
|
||||
|
||||
@@ -102,7 +100,7 @@ abstract class AbstractGrant implements GrantTypeInterface
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \League\OAuth2\Server\Repositories\RefreshTokenRepositoryInterface $refreshTokenRepository
|
||||
* @param RefreshTokenRepositoryInterface $refreshTokenRepository
|
||||
*/
|
||||
public function setRefreshTokenRepository(RefreshTokenRepositoryInterface $refreshTokenRepository)
|
||||
{
|
||||
@@ -110,7 +108,7 @@ abstract class AbstractGrant implements GrantTypeInterface
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \League\OAuth2\Server\Repositories\AuthCodeRepositoryInterface $authCodeRepository
|
||||
* @param AuthCodeRepositoryInterface $authCodeRepository
|
||||
*/
|
||||
public function setAuthCodeRepository(AuthCodeRepositoryInterface $authCodeRepository)
|
||||
{
|
||||
@@ -118,7 +116,7 @@ abstract class AbstractGrant implements GrantTypeInterface
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \League\OAuth2\Server\Repositories\UserRepositoryInterface $userRepository
|
||||
* @param UserRepositoryInterface $userRepository
|
||||
*/
|
||||
public function setUserRepository(UserRepositoryInterface $userRepository)
|
||||
{
|
||||
@@ -136,45 +134,52 @@ abstract class AbstractGrant implements GrantTypeInterface
|
||||
/**
|
||||
* Validate the client.
|
||||
*
|
||||
* @param \Psr\Http\Message\ServerRequestInterface $request
|
||||
* @param ServerRequestInterface $request
|
||||
*
|
||||
* @throws \League\OAuth2\Server\Exception\OAuthServerException
|
||||
* @throws OAuthServerException
|
||||
*
|
||||
* @return \League\OAuth2\Server\Entities\Interfaces\ClientEntityInterface
|
||||
* @return ClientEntityInterface
|
||||
*/
|
||||
protected function validateClient(ServerRequestInterface $request)
|
||||
{
|
||||
$clientId = $this->getRequestParameter(
|
||||
'client_id',
|
||||
$request,
|
||||
$this->getServerParameter('PHP_AUTH_USER', $request)
|
||||
);
|
||||
list($basicAuthUser, $basicAuthPassword) = $this->getBasicAuthCredentials($request);
|
||||
|
||||
$clientId = $this->getRequestParameter('client_id', $request, $basicAuthUser);
|
||||
if (is_null($clientId)) {
|
||||
throw OAuthServerException::invalidRequest('client_id', '`%s` parameter is missing');
|
||||
throw OAuthServerException::invalidRequest('client_id');
|
||||
}
|
||||
|
||||
// If the client is confidential require the client secret
|
||||
$clientSecret = $this->getRequestParameter(
|
||||
'client_secret',
|
||||
$request,
|
||||
$this->getServerParameter('PHP_AUTH_PW', $request)
|
||||
);
|
||||
$clientSecret = $this->getRequestParameter('client_secret', $request, $basicAuthPassword);
|
||||
|
||||
$client = $this->clientRepository->getClientEntity(
|
||||
$clientId,
|
||||
$this->getIdentifier(),
|
||||
$clientSecret
|
||||
$clientSecret,
|
||||
true
|
||||
);
|
||||
|
||||
if (!$client instanceof ClientEntityInterface) {
|
||||
$this->getEmitter()->emit(new RequestEvent('client.authentication.failed', $request));
|
||||
if ($client instanceof ClientEntityInterface === false) {
|
||||
$this->getEmitter()->emit(new RequestEvent(RequestEvent::CLIENT_AUTHENTICATION_FAILED, $request));
|
||||
throw OAuthServerException::invalidClient();
|
||||
}
|
||||
|
||||
// If a redirect URI is provided ensure it matches what is pre-registered
|
||||
$redirectUri = $this->getRequestParameter('redirect_uri', $request, null);
|
||||
if ($redirectUri !== null && (strcmp($client->getRedirectUri(), $redirectUri) !== 0)) {
|
||||
throw OAuthServerException::invalidClient();
|
||||
if ($redirectUri !== null) {
|
||||
if (
|
||||
is_string($client->getRedirectUri())
|
||||
&& (strcmp($client->getRedirectUri(), $redirectUri) !== 0)
|
||||
) {
|
||||
$this->getEmitter()->emit(new RequestEvent(RequestEvent::CLIENT_AUTHENTICATION_FAILED, $request));
|
||||
throw OAuthServerException::invalidClient();
|
||||
} elseif (
|
||||
is_array($client->getRedirectUri())
|
||||
&& in_array($redirectUri, $client->getRedirectUri()) === false
|
||||
) {
|
||||
$this->getEmitter()->emit(new RequestEvent(RequestEvent::CLIENT_AUTHENTICATION_FAILED, $request));
|
||||
throw OAuthServerException::invalidClient();
|
||||
}
|
||||
}
|
||||
|
||||
return $client;
|
||||
@@ -183,17 +188,15 @@ abstract class AbstractGrant implements GrantTypeInterface
|
||||
/**
|
||||
* Validate scopes in the request.
|
||||
*
|
||||
* @param string $scopes
|
||||
* @param \League\OAuth2\Server\Entities\Interfaces\ClientEntityInterface $client
|
||||
* @param string $redirectUri
|
||||
* @param string $scopes
|
||||
* @param string $redirectUri
|
||||
*
|
||||
* @throws \League\OAuth2\Server\Exception\OAuthServerException
|
||||
* @throws OAuthServerException
|
||||
*
|
||||
* @return \League\OAuth2\Server\Entities\Interfaces\ScopeEntityInterface[]
|
||||
* @return ScopeEntityInterface[]
|
||||
*/
|
||||
public function validateScopes(
|
||||
$scopes,
|
||||
ClientEntityInterface $client,
|
||||
$redirectUri = null
|
||||
) {
|
||||
$scopesList = array_filter(
|
||||
@@ -207,7 +210,7 @@ abstract class AbstractGrant implements GrantTypeInterface
|
||||
foreach ($scopesList as $scopeItem) {
|
||||
$scope = $this->scopeRepository->getScopeEntityByIdentifier($scopeItem);
|
||||
|
||||
if (($scope instanceof ScopeEntityInterface) === false) {
|
||||
if ($scope instanceof ScopeEntityInterface === false) {
|
||||
throw OAuthServerException::invalidScope($scopeItem, $redirectUri);
|
||||
}
|
||||
|
||||
@@ -220,9 +223,9 @@ abstract class AbstractGrant implements GrantTypeInterface
|
||||
/**
|
||||
* Retrieve request parameter.
|
||||
*
|
||||
* @param string $parameter
|
||||
* @param \Psr\Http\Message\ServerRequestInterface $request
|
||||
* @param mixed $default
|
||||
* @param string $parameter
|
||||
* @param ServerRequestInterface $request
|
||||
* @param mixed $default
|
||||
*
|
||||
* @return null|string
|
||||
*/
|
||||
@@ -233,12 +236,45 @@ abstract class AbstractGrant implements GrantTypeInterface
|
||||
return isset($requestParameters[$parameter]) ? $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 \Psr\Http\Message\ServerRequestInterface $request
|
||||
* @param mixed $default
|
||||
* @param string $parameter
|
||||
* @param ServerRequestInterface $request
|
||||
* @param mixed $default
|
||||
*
|
||||
* @return null|string
|
||||
*/
|
||||
@@ -250,9 +286,9 @@ abstract class AbstractGrant implements GrantTypeInterface
|
||||
/**
|
||||
* Retrieve cookie parameter.
|
||||
*
|
||||
* @param string $parameter
|
||||
* @param \Psr\Http\Message\ServerRequestInterface $request
|
||||
* @param mixed $default
|
||||
* @param string $parameter
|
||||
* @param ServerRequestInterface $request
|
||||
* @param mixed $default
|
||||
*
|
||||
* @return null|string
|
||||
*/
|
||||
@@ -264,9 +300,9 @@ abstract class AbstractGrant implements GrantTypeInterface
|
||||
/**
|
||||
* Retrieve server parameter.
|
||||
*
|
||||
* @param string $parameter
|
||||
* @param \Psr\Http\Message\ServerRequestInterface $request
|
||||
* @param mixed $default
|
||||
* @param string $parameter
|
||||
* @param ServerRequestInterface $request
|
||||
* @param mixed $default
|
||||
*
|
||||
* @return null|string
|
||||
*/
|
||||
@@ -278,12 +314,15 @@ abstract class AbstractGrant implements GrantTypeInterface
|
||||
/**
|
||||
* Issue an access token.
|
||||
*
|
||||
* @param \DateInterval $accessTokenTTL
|
||||
* @param \League\OAuth2\Server\Entities\Interfaces\ClientEntityInterface $client
|
||||
* @param string $userIdentifier
|
||||
* @param \League\OAuth2\Server\Entities\Interfaces\ScopeEntityInterface[] $scopes
|
||||
* @param \DateInterval $accessTokenTTL
|
||||
* @param ClientEntityInterface $client
|
||||
* @param string $userIdentifier
|
||||
* @param ScopeEntityInterface[] $scopes
|
||||
*
|
||||
* @return \League\OAuth2\Server\Entities\Interfaces\AccessTokenEntityInterface
|
||||
* @throws OAuthServerException
|
||||
* @throws UniqueTokenIdentifierConstraintViolationException
|
||||
*
|
||||
* @return AccessTokenEntityInterface
|
||||
*/
|
||||
protected function issueAccessToken(
|
||||
\DateInterval $accessTokenTTL,
|
||||
@@ -291,31 +330,44 @@ abstract class AbstractGrant implements GrantTypeInterface
|
||||
$userIdentifier,
|
||||
array $scopes = []
|
||||
) {
|
||||
$accessToken = new AccessTokenEntity();
|
||||
$accessToken->setIdentifier($this->generateUniqueIdentifier());
|
||||
$accessToken->setExpiryDateTime((new \DateTime())->add($accessTokenTTL));
|
||||
$maxGenerationAttempts = self::MAX_RANDOM_TOKEN_GENERATION_ATTEMPTS;
|
||||
|
||||
$accessToken = $this->accessTokenRepository->getNewToken($client, $scopes, $userIdentifier);
|
||||
$accessToken->setClient($client);
|
||||
$accessToken->setUserIdentifier($userIdentifier);
|
||||
$accessToken->setExpiryDateTime((new \DateTime())->add($accessTokenTTL));
|
||||
|
||||
foreach ($scopes as $scope) {
|
||||
$accessToken->addScope($scope);
|
||||
}
|
||||
|
||||
$this->accessTokenRepository->persistNewAccessToken($accessToken);
|
||||
while ($maxGenerationAttempts-- > 0) {
|
||||
$accessToken->setIdentifier($this->generateUniqueIdentifier());
|
||||
try {
|
||||
$this->accessTokenRepository->persistNewAccessToken($accessToken);
|
||||
|
||||
return $accessToken;
|
||||
return $accessToken;
|
||||
} catch (UniqueTokenIdentifierConstraintViolationException $e) {
|
||||
if ($maxGenerationAttempts === 0) {
|
||||
throw $e;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Issue an auth code.
|
||||
*
|
||||
* @param \DateInterval $authCodeTTL
|
||||
* @param \League\OAuth2\Server\Entities\Interfaces\ClientEntityInterface $client
|
||||
* @param string $userIdentifier
|
||||
* @param string $redirectUri
|
||||
* @param \League\OAuth2\Server\Entities\Interfaces\ScopeEntityInterface[] $scopes
|
||||
* @param \DateInterval $authCodeTTL
|
||||
* @param ClientEntityInterface $client
|
||||
* @param string $userIdentifier
|
||||
* @param string $redirectUri
|
||||
* @param ScopeEntityInterface[] $scopes
|
||||
*
|
||||
* @return \League\OAuth2\Server\Entities\Interfaces\AuthCodeEntityInterface
|
||||
* @throws OAuthServerException
|
||||
* @throws UniqueTokenIdentifierConstraintViolationException
|
||||
*
|
||||
* @return AuthCodeEntityInterface
|
||||
*/
|
||||
protected function issueAuthCode(
|
||||
\DateInterval $authCodeTTL,
|
||||
@@ -324,8 +376,9 @@ abstract class AbstractGrant implements GrantTypeInterface
|
||||
$redirectUri,
|
||||
array $scopes = []
|
||||
) {
|
||||
$authCode = new AuthCodeEntity();
|
||||
$authCode->setIdentifier($this->generateUniqueIdentifier());
|
||||
$maxGenerationAttempts = self::MAX_RANDOM_TOKEN_GENERATION_ATTEMPTS;
|
||||
|
||||
$authCode = $this->authCodeRepository->getNewAuthCode();
|
||||
$authCode->setExpiryDateTime((new \DateTime())->add($authCodeTTL));
|
||||
$authCode->setClient($client);
|
||||
$authCode->setUserIdentifier($userIdentifier);
|
||||
@@ -335,26 +388,48 @@ abstract class AbstractGrant implements GrantTypeInterface
|
||||
$authCode->addScope($scope);
|
||||
}
|
||||
|
||||
$this->authCodeRepository->persistNewAuthCode($authCode);
|
||||
while ($maxGenerationAttempts-- > 0) {
|
||||
$authCode->setIdentifier($this->generateUniqueIdentifier());
|
||||
try {
|
||||
$this->authCodeRepository->persistNewAuthCode($authCode);
|
||||
|
||||
return $authCode;
|
||||
return $authCode;
|
||||
} catch (UniqueTokenIdentifierConstraintViolationException $e) {
|
||||
if ($maxGenerationAttempts === 0) {
|
||||
throw $e;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \League\OAuth2\Server\Entities\Interfaces\AccessTokenEntityInterface $accessToken
|
||||
* @param AccessTokenEntityInterface $accessToken
|
||||
*
|
||||
* @return \League\OAuth2\Server\Entities\Interfaces\RefreshTokenEntityInterface
|
||||
* @throws OAuthServerException
|
||||
* @throws UniqueTokenIdentifierConstraintViolationException
|
||||
*
|
||||
* @return RefreshTokenEntityInterface
|
||||
*/
|
||||
protected function issueRefreshToken(AccessTokenEntityInterface $accessToken)
|
||||
{
|
||||
$refreshToken = new RefreshTokenEntity();
|
||||
$refreshToken->setIdentifier($this->generateUniqueIdentifier());
|
||||
$maxGenerationAttempts = self::MAX_RANDOM_TOKEN_GENERATION_ATTEMPTS;
|
||||
|
||||
$refreshToken = $this->refreshTokenRepository->getNewRefreshToken();
|
||||
$refreshToken->setExpiryDateTime((new \DateTime())->add($this->refreshTokenTTL));
|
||||
$refreshToken->setAccessToken($accessToken);
|
||||
|
||||
$this->refreshTokenRepository->persistNewRefreshToken($refreshToken);
|
||||
while ($maxGenerationAttempts-- > 0) {
|
||||
$refreshToken->setIdentifier($this->generateUniqueIdentifier());
|
||||
try {
|
||||
$this->refreshTokenRepository->persistNewRefreshToken($refreshToken);
|
||||
|
||||
return $refreshToken;
|
||||
return $refreshToken;
|
||||
} catch (UniqueTokenIdentifierConstraintViolationException $e) {
|
||||
if ($maxGenerationAttempts === 0) {
|
||||
throw $e;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -362,7 +437,7 @@ abstract class AbstractGrant implements GrantTypeInterface
|
||||
*
|
||||
* @param int $length
|
||||
*
|
||||
* @throws \League\OAuth2\Server\Exception\OAuthServerException
|
||||
* @throws OAuthServerException
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
@@ -385,7 +460,7 @@ abstract class AbstractGrant implements GrantTypeInterface
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function canRespondToRequest(ServerRequestInterface $request)
|
||||
public function canRespondToAccessTokenRequest(ServerRequestInterface $request)
|
||||
{
|
||||
$requestParameters = (array) $request->getParsedBody();
|
||||
|
||||
@@ -394,4 +469,28 @@ abstract class AbstractGrant implements GrantTypeInterface
|
||||
&& $requestParameters['grant_type'] === $this->getIdentifier()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function canRespondToAuthorizationRequest(ServerRequestInterface $request)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function validateAuthorizationRequest(ServerRequestInterface $request)
|
||||
{
|
||||
throw new \LogicException('This grant cannot validate an authorization request');
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function completeAuthorizationRequest(AuthorizationRequest $authorizationRequest)
|
||||
{
|
||||
throw new \LogicException('This grant cannot complete an authorization request');
|
||||
}
|
||||
}
|
||||
|
@@ -1,19 +1,24 @@
|
||||
<?php
|
||||
/**
|
||||
* @author Alex Bilbie <hello@alexbilbie.com>
|
||||
* @copyright Copyright (c) Alex Bilbie
|
||||
* @license http://mit-license.org/
|
||||
*
|
||||
* @link https://github.com/thephpleague/oauth2-server
|
||||
*/
|
||||
|
||||
namespace League\OAuth2\Server\Grant;
|
||||
|
||||
use DateInterval;
|
||||
use League\OAuth2\Server\Entities\Interfaces\ClientEntityInterface;
|
||||
use League\OAuth2\Server\Entities\Interfaces\UserEntityInterface;
|
||||
use League\OAuth2\Server\Entities\ClientEntityInterface;
|
||||
use League\OAuth2\Server\Entities\ScopeEntityInterface;
|
||||
use League\OAuth2\Server\Entities\UserEntityInterface;
|
||||
use League\OAuth2\Server\Exception\OAuthServerException;
|
||||
use League\OAuth2\Server\Repositories\AuthCodeRepositoryInterface;
|
||||
use League\OAuth2\Server\Repositories\RefreshTokenRepositoryInterface;
|
||||
use League\OAuth2\Server\Repositories\UserRepositoryInterface;
|
||||
use League\OAuth2\Server\RequestEvent;
|
||||
use League\OAuth2\Server\ResponseTypes\HtmlResponse;
|
||||
use League\OAuth2\Server\RequestTypes\AuthorizationRequest;
|
||||
use League\OAuth2\Server\ResponseTypes\RedirectResponse;
|
||||
use League\OAuth2\Server\ResponseTypes\ResponseTypeInterface;
|
||||
use League\OAuth2\Server\TemplateRenderer\RendererInterface;
|
||||
use Psr\Http\Message\ServerRequestInterface;
|
||||
|
||||
class AuthCodeGrant extends AbstractAuthorizeGrant
|
||||
@@ -24,234 +29,47 @@ class AuthCodeGrant extends AbstractAuthorizeGrant
|
||||
private $authCodeTTL;
|
||||
|
||||
/**
|
||||
* @param \League\OAuth2\Server\Repositories\AuthCodeRepositoryInterface $authCodeRepository
|
||||
* @param \League\OAuth2\Server\Repositories\RefreshTokenRepositoryInterface $refreshTokenRepository
|
||||
* @param \League\OAuth2\Server\Repositories\UserRepositoryInterface $userRepository
|
||||
* @param \DateInterval $authCodeTTL
|
||||
* @param \League\OAuth2\Server\TemplateRenderer\RendererInterface|null $templateRenderer
|
||||
* @var bool
|
||||
*/
|
||||
private $enableCodeExchangeProof = false;
|
||||
|
||||
/**
|
||||
* @param AuthCodeRepositoryInterface $authCodeRepository
|
||||
* @param RefreshTokenRepositoryInterface $refreshTokenRepository
|
||||
* @param \DateInterval $authCodeTTL
|
||||
*/
|
||||
public function __construct(
|
||||
AuthCodeRepositoryInterface $authCodeRepository,
|
||||
RefreshTokenRepositoryInterface $refreshTokenRepository,
|
||||
UserRepositoryInterface $userRepository,
|
||||
\DateInterval $authCodeTTL,
|
||||
RendererInterface $templateRenderer = null
|
||||
\DateInterval $authCodeTTL
|
||||
) {
|
||||
$this->setAuthCodeRepository($authCodeRepository);
|
||||
$this->setRefreshTokenRepository($refreshTokenRepository);
|
||||
$this->setUserRepository($userRepository);
|
||||
$this->authCodeTTL = $authCodeTTL;
|
||||
$this->refreshTokenTTL = new \DateInterval('P1M');
|
||||
$this->templateRenderer = $templateRenderer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Respond to an authorization request.
|
||||
*
|
||||
* @param \Psr\Http\Message\ServerRequestInterface $request
|
||||
*
|
||||
* @throws \League\OAuth2\Server\Exception\OAuthServerException
|
||||
*
|
||||
* @return \Psr\Http\Message\ResponseInterface
|
||||
*/
|
||||
protected function respondToAuthorizationRequest(
|
||||
ServerRequestInterface $request
|
||||
) {
|
||||
$clientId = $this->getQueryStringParameter(
|
||||
'client_id',
|
||||
$request,
|
||||
$this->getServerParameter('PHP_AUTH_USER', $request)
|
||||
);
|
||||
if (is_null($clientId)) {
|
||||
throw OAuthServerException::invalidRequest('client_id');
|
||||
}
|
||||
|
||||
$client = $this->clientRepository->getClientEntity(
|
||||
$clientId,
|
||||
$this->getIdentifier()
|
||||
);
|
||||
|
||||
if ($client instanceof ClientEntityInterface === false) {
|
||||
$this->getEmitter()->emit(new RequestEvent('client.authentication.failed', $request));
|
||||
throw OAuthServerException::invalidClient();
|
||||
}
|
||||
|
||||
$redirectUriParameter = $this->getQueryStringParameter('redirect_uri', $request, $client->getRedirectUri());
|
||||
if ($redirectUriParameter !== $client->getRedirectUri()) {
|
||||
$this->getEmitter()->emit(new RequestEvent('client.authentication.failed', $request));
|
||||
throw OAuthServerException::invalidClient();
|
||||
}
|
||||
|
||||
$scopes = $this->validateScopes(
|
||||
$this->getQueryStringParameter('scope', $request),
|
||||
$client,
|
||||
$client->getRedirectUri()
|
||||
);
|
||||
|
||||
$postbackUri = sprintf(
|
||||
'//%s%s',
|
||||
$request->getServerParams()['HTTP_HOST'],
|
||||
$request->getServerParams()['REQUEST_URI']
|
||||
);
|
||||
|
||||
$userId = null;
|
||||
$userHasApprovedClient = null;
|
||||
if ($this->getRequestParameter('action', $request, null) !== null) {
|
||||
$userHasApprovedClient = ($this->getRequestParameter('action', $request) === 'approve');
|
||||
}
|
||||
|
||||
// Check if the user has been authenticated
|
||||
$oauthCookie = $this->getCookieParameter('oauth_authorize_request', $request, null);
|
||||
if ($oauthCookie !== null) {
|
||||
try {
|
||||
$oauthCookiePayload = json_decode($this->decrypt($oauthCookie));
|
||||
if (is_object($oauthCookiePayload)) {
|
||||
$userId = $oauthCookiePayload->user_id;
|
||||
}
|
||||
} catch (\LogicException $e) {
|
||||
throw OAuthServerException::serverError($e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
// The username + password might be available in $_POST
|
||||
$usernameParameter = $this->getRequestParameter('username', $request, null);
|
||||
$passwordParameter = $this->getRequestParameter('password', $request, null);
|
||||
|
||||
$loginError = null;
|
||||
|
||||
// Assert if the user has logged in already
|
||||
if ($userId === null && $usernameParameter !== null && $passwordParameter !== null) {
|
||||
$userEntity = $this->userRepository->getUserEntityByUserCredentials(
|
||||
$usernameParameter,
|
||||
$passwordParameter,
|
||||
$this->getIdentifier(),
|
||||
$client
|
||||
);
|
||||
|
||||
if ($userEntity instanceof UserEntityInterface) {
|
||||
$userId = $userEntity->getIdentifier();
|
||||
} else {
|
||||
$loginError = 'Incorrect username or password';
|
||||
}
|
||||
}
|
||||
|
||||
// The user hasn't logged in yet so show a login form
|
||||
if ($userId === null) {
|
||||
$html = $this->getTemplateRenderer()->renderLogin([
|
||||
'error' => $loginError,
|
||||
'postback_uri' => $this->makeRedirectUri(
|
||||
$postbackUri,
|
||||
$request->getQueryParams()
|
||||
),
|
||||
]);
|
||||
|
||||
$htmlResponse = new HtmlResponse($this->accessTokenRepository);
|
||||
$htmlResponse->setStatusCode(403);
|
||||
$htmlResponse->setHtml($html);
|
||||
|
||||
return $htmlResponse;
|
||||
}
|
||||
|
||||
// The user hasn't approved the client yet so show an authorize form
|
||||
if ($userId !== null && $userHasApprovedClient === null) {
|
||||
$html = $this->getTemplateRenderer()->renderAuthorize([
|
||||
'client' => $client,
|
||||
'scopes' => $scopes,
|
||||
'postback_uri' => $this->makeRedirectUri(
|
||||
$postbackUri,
|
||||
$request->getQueryParams()
|
||||
),
|
||||
]);
|
||||
|
||||
$htmlResponse = new HtmlResponse($this->accessTokenRepository);
|
||||
$htmlResponse->setStatusCode(200);
|
||||
$htmlResponse->setHtml($html);
|
||||
$htmlResponse->setHeader('set-cookie', sprintf(
|
||||
'oauth_authorize_request=%s; Expires=%s',
|
||||
urlencode($this->encrypt(
|
||||
json_encode([
|
||||
'user_id' => $userId,
|
||||
])
|
||||
)),
|
||||
(new \DateTime())->add(new \DateInterval('PT5M'))->format('D, d M Y H:i:s e')
|
||||
));
|
||||
|
||||
return $htmlResponse;
|
||||
}
|
||||
|
||||
// The user has either approved or denied the client, so redirect them back
|
||||
$redirectUri = $client->getRedirectUri();
|
||||
$redirectPayload = [];
|
||||
|
||||
$stateParameter = $this->getQueryStringParameter('state', $request);
|
||||
if ($stateParameter !== null) {
|
||||
$redirectPayload['state'] = $stateParameter;
|
||||
}
|
||||
|
||||
// THe user approved the client, redirect them back with an auth code
|
||||
if ($userHasApprovedClient === true) {
|
||||
|
||||
// Finalize the requested scopes
|
||||
$scopes = $this->scopeRepository->finalizeScopes($scopes, $this->getIdentifier(), $client, $userId);
|
||||
|
||||
$authCode = $this->issueAuthCode(
|
||||
$this->authCodeTTL,
|
||||
$client,
|
||||
$userId,
|
||||
$redirectUri,
|
||||
$scopes
|
||||
);
|
||||
|
||||
$redirectPayload['code'] = $this->encrypt(
|
||||
json_encode(
|
||||
[
|
||||
'client_id' => $authCode->getClient()->getIdentifier(),
|
||||
'redirect_uri' => $authCode->getRedirectUri(),
|
||||
'auth_code_id' => $authCode->getIdentifier(),
|
||||
'scopes' => $authCode->getScopes(),
|
||||
'user_id' => $authCode->getUserIdentifier(),
|
||||
'expire_time' => (new \DateTime())->add($this->authCodeTTL)->format('U'),
|
||||
]
|
||||
)
|
||||
);
|
||||
|
||||
$response = new RedirectResponse($this->accessTokenRepository);
|
||||
$response->setRedirectUri(
|
||||
$this->makeRedirectUri(
|
||||
$redirectUri,
|
||||
$redirectPayload
|
||||
)
|
||||
);
|
||||
|
||||
return $response;
|
||||
}
|
||||
|
||||
// The user denied the client, redirect them back with an error
|
||||
throw OAuthServerException::accessDenied('The user denied the request', (string) $redirectUri);
|
||||
public function enableCodeExchangeProof()
|
||||
{
|
||||
$this->enableCodeExchangeProof = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Respond to an access token request.
|
||||
*
|
||||
* @param \Psr\Http\Message\ServerRequestInterface $request
|
||||
* @param \League\OAuth2\Server\ResponseTypes\ResponseTypeInterface $responseType
|
||||
* @param \DateInterval $accessTokenTTL
|
||||
* @param ServerRequestInterface $request
|
||||
* @param ResponseTypeInterface $responseType
|
||||
* @param \DateInterval $accessTokenTTL
|
||||
*
|
||||
* @throws \League\OAuth2\Server\Exception\OAuthServerException
|
||||
* @throws OAuthServerException
|
||||
*
|
||||
* @return \League\OAuth2\Server\ResponseTypes\ResponseTypeInterface
|
||||
* @return ResponseTypeInterface
|
||||
*/
|
||||
protected function respondToAccessTokenRequest(
|
||||
public function respondToAccessTokenRequest(
|
||||
ServerRequestInterface $request,
|
||||
ResponseTypeInterface $responseType,
|
||||
DateInterval $accessTokenTTL
|
||||
\DateInterval $accessTokenTTL
|
||||
) {
|
||||
// The redirect URI is required in this request
|
||||
$redirectUri = $this->getRequestParameter('redirect_uri', $request, null);
|
||||
if (is_null($redirectUri)) {
|
||||
throw OAuthServerException::invalidRequest('redirect_uri');
|
||||
}
|
||||
|
||||
// Validate request
|
||||
$client = $this->validateClient($request);
|
||||
$encryptedAuthCode = $this->getRequestParameter('code', $request, null);
|
||||
@@ -275,6 +93,12 @@ class AuthCodeGrant extends AbstractAuthorizeGrant
|
||||
throw OAuthServerException::invalidRequest('code', 'Authorization code was not issued to this client');
|
||||
}
|
||||
|
||||
// The redirect URI is required in this request
|
||||
$redirectUri = $this->getRequestParameter('redirect_uri', $request, null);
|
||||
if (empty($authCodePayload->redirect_uri) === false && $redirectUri === null) {
|
||||
throw OAuthServerException::invalidRequest('redirect_uri');
|
||||
}
|
||||
|
||||
if ($authCodePayload->redirect_uri !== $redirectUri) {
|
||||
throw OAuthServerException::invalidRequest('redirect_uri', 'Invalid redirect URI');
|
||||
}
|
||||
@@ -283,7 +107,7 @@ class AuthCodeGrant extends AbstractAuthorizeGrant
|
||||
foreach ($authCodePayload->scopes as $scopeId) {
|
||||
$scope = $this->scopeRepository->getScopeEntityByIdentifier($scopeId);
|
||||
|
||||
if (!$scope) {
|
||||
if ($scope instanceof ScopeEntityInterface === false) {
|
||||
// @codeCoverageIgnoreStart
|
||||
throw OAuthServerException::invalidScope($scopeId);
|
||||
// @codeCoverageIgnoreEnd
|
||||
@@ -291,10 +115,54 @@ class AuthCodeGrant extends AbstractAuthorizeGrant
|
||||
|
||||
$scopes[] = $scope;
|
||||
}
|
||||
|
||||
// Finalize the requested scopes
|
||||
$scopes = $this->scopeRepository->finalizeScopes(
|
||||
$scopes,
|
||||
$this->getIdentifier(),
|
||||
$client,
|
||||
$authCodePayload->user_id
|
||||
);
|
||||
} catch (\LogicException $e) {
|
||||
throw OAuthServerException::invalidRequest('code', 'Cannot decrypt the authorization code');
|
||||
}
|
||||
|
||||
// Validate code challenge
|
||||
if ($this->enableCodeExchangeProof === true) {
|
||||
$codeVerifier = $this->getRequestParameter('code_verifier', $request, null);
|
||||
if ($codeVerifier === null) {
|
||||
throw OAuthServerException::invalidRequest('code_verifier');
|
||||
}
|
||||
|
||||
switch ($authCodePayload->code_challenge_method) {
|
||||
case 'plain':
|
||||
if (hash_equals($codeVerifier, $authCodePayload->code_challenge) === false) {
|
||||
throw OAuthServerException::invalidGrant('Failed to verify `code_verifier`.');
|
||||
}
|
||||
|
||||
break;
|
||||
case 'S256':
|
||||
if (
|
||||
hash_equals(
|
||||
urlencode(base64_encode(hash('sha256', $codeVerifier))),
|
||||
$authCodePayload->code_challenge
|
||||
) === false
|
||||
) {
|
||||
throw OAuthServerException::invalidGrant('Failed to verify `code_verifier`.');
|
||||
}
|
||||
// @codeCoverageIgnoreStart
|
||||
break;
|
||||
default:
|
||||
throw OAuthServerException::serverError(
|
||||
sprintf(
|
||||
'Unsupported code challenge method `%s`',
|
||||
$authCodePayload->code_challenge_method
|
||||
)
|
||||
);
|
||||
// @codeCoverageIgnoreEnd
|
||||
}
|
||||
}
|
||||
|
||||
// Issue and persist access + refresh tokens
|
||||
$accessToken = $this->issueAccessToken($accessTokenTTL, $client, $authCodePayload->user_id, $scopes);
|
||||
$refreshToken = $this->issueRefreshToken($accessToken);
|
||||
@@ -303,41 +171,12 @@ class AuthCodeGrant extends AbstractAuthorizeGrant
|
||||
$responseType->setAccessToken($accessToken);
|
||||
$responseType->setRefreshToken($refreshToken);
|
||||
|
||||
// Revoke used auth code
|
||||
$this->authCodeRepository->revokeAuthCode($authCodePayload->auth_code_id);
|
||||
|
||||
return $responseType;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function respondToRequest(
|
||||
ServerRequestInterface $request,
|
||||
ResponseTypeInterface $responseType,
|
||||
\DateInterval $accessTokenTTL
|
||||
) {
|
||||
if (
|
||||
array_key_exists('response_type', $request->getQueryParams())
|
||||
&& $request->getQueryParams()['response_type'] === 'code'
|
||||
) {
|
||||
return $this->respondToAuthorizationRequest($request);
|
||||
}
|
||||
|
||||
return $this->respondToAccessTokenRequest($request, $responseType, $accessTokenTTL);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function canRespondToRequest(ServerRequestInterface $request)
|
||||
{
|
||||
return
|
||||
(
|
||||
array_key_exists('response_type', $request->getQueryParams())
|
||||
&& $request->getQueryParams()['response_type'] === 'code'
|
||||
&& isset($request->getQueryParams()['client_id'])
|
||||
)
|
||||
|| parent::canRespondToRequest($request);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the grant identifier that can be used in matching up requests.
|
||||
*
|
||||
@@ -347,4 +186,160 @@ class AuthCodeGrant extends AbstractAuthorizeGrant
|
||||
{
|
||||
return 'authorization_code';
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function canRespondToAuthorizationRequest(ServerRequestInterface $request)
|
||||
{
|
||||
return (
|
||||
array_key_exists('response_type', $request->getQueryParams())
|
||||
&& $request->getQueryParams()['response_type'] === 'code'
|
||||
&& isset($request->getQueryParams()['client_id'])
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function validateAuthorizationRequest(ServerRequestInterface $request)
|
||||
{
|
||||
$clientId = $this->getQueryStringParameter(
|
||||
'client_id',
|
||||
$request,
|
||||
$this->getServerParameter('PHP_AUTH_USER', $request)
|
||||
);
|
||||
if (is_null($clientId)) {
|
||||
throw OAuthServerException::invalidRequest('client_id');
|
||||
}
|
||||
|
||||
$client = $this->clientRepository->getClientEntity(
|
||||
$clientId,
|
||||
$this->getIdentifier(),
|
||||
null,
|
||||
false
|
||||
);
|
||||
|
||||
if ($client instanceof ClientEntityInterface === false) {
|
||||
$this->getEmitter()->emit(new RequestEvent(RequestEvent::CLIENT_AUTHENTICATION_FAILED, $request));
|
||||
throw OAuthServerException::invalidClient();
|
||||
}
|
||||
|
||||
$redirectUri = $this->getQueryStringParameter('redirect_uri', $request);
|
||||
if ($redirectUri !== null) {
|
||||
if (
|
||||
is_string($client->getRedirectUri())
|
||||
&& (strcmp($client->getRedirectUri(), $redirectUri) !== 0)
|
||||
) {
|
||||
$this->getEmitter()->emit(new RequestEvent(RequestEvent::CLIENT_AUTHENTICATION_FAILED, $request));
|
||||
throw OAuthServerException::invalidClient();
|
||||
} elseif (
|
||||
is_array($client->getRedirectUri())
|
||||
&& in_array($redirectUri, $client->getRedirectUri()) === false
|
||||
) {
|
||||
$this->getEmitter()->emit(new RequestEvent(RequestEvent::CLIENT_AUTHENTICATION_FAILED, $request));
|
||||
throw OAuthServerException::invalidClient();
|
||||
}
|
||||
}
|
||||
|
||||
$scopes = $this->validateScopes(
|
||||
$this->getQueryStringParameter('scope', $request),
|
||||
is_array($client->getRedirectUri())
|
||||
? $client->getRedirectUri()[0]
|
||||
: $client->getRedirectUri()
|
||||
);
|
||||
|
||||
$stateParameter = $this->getQueryStringParameter('state', $request);
|
||||
|
||||
$authorizationRequest = new AuthorizationRequest();
|
||||
$authorizationRequest->setGrantTypeId($this->getIdentifier());
|
||||
$authorizationRequest->setClient($client);
|
||||
$authorizationRequest->setRedirectUri($redirectUri);
|
||||
$authorizationRequest->setState($stateParameter);
|
||||
$authorizationRequest->setScopes($scopes);
|
||||
|
||||
if ($this->enableCodeExchangeProof === true) {
|
||||
$codeChallenge = $this->getQueryStringParameter('code_challenge', $request);
|
||||
if ($codeChallenge === null) {
|
||||
throw OAuthServerException::invalidRequest('code_challenge');
|
||||
}
|
||||
|
||||
$codeChallengeMethod = $this->getQueryStringParameter('code_challenge_method', $request, 'plain');
|
||||
if (in_array($codeChallengeMethod, ['plain', 'S256']) === false) {
|
||||
throw OAuthServerException::invalidRequest(
|
||||
'code_challenge_method',
|
||||
'Code challenge method must be `plain` or `S256`'
|
||||
);
|
||||
}
|
||||
|
||||
$authorizationRequest->setCodeChallenge($codeChallenge);
|
||||
$authorizationRequest->setCodeChallengeMethod($codeChallengeMethod);
|
||||
}
|
||||
|
||||
return $authorizationRequest;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function completeAuthorizationRequest(AuthorizationRequest $authorizationRequest)
|
||||
{
|
||||
if ($authorizationRequest->getUser() instanceof UserEntityInterface === false) {
|
||||
throw new \LogicException('An instance of UserEntityInterface should be set on the AuthorizationRequest');
|
||||
}
|
||||
|
||||
$finalRedirectUri = ($authorizationRequest->getRedirectUri() === null)
|
||||
? is_array($authorizationRequest->getClient()->getRedirectUri())
|
||||
? $authorizationRequest->getClient()->getRedirectUri()[0]
|
||||
: $authorizationRequest->getClient()->getRedirectUri()
|
||||
: $authorizationRequest->getRedirectUri();
|
||||
|
||||
// The user approved the client, redirect them back with an auth code
|
||||
if ($authorizationRequest->isAuthorizationApproved() === true) {
|
||||
$authCode = $this->issueAuthCode(
|
||||
$this->authCodeTTL,
|
||||
$authorizationRequest->getClient(),
|
||||
$authorizationRequest->getUser()->getIdentifier(),
|
||||
$authorizationRequest->getRedirectUri(),
|
||||
$authorizationRequest->getScopes()
|
||||
);
|
||||
|
||||
$response = new RedirectResponse();
|
||||
$response->setRedirectUri(
|
||||
$this->makeRedirectUri(
|
||||
$finalRedirectUri,
|
||||
[
|
||||
'code' => $this->encrypt(
|
||||
json_encode(
|
||||
[
|
||||
'client_id' => $authCode->getClient()->getIdentifier(),
|
||||
'redirect_uri' => $authCode->getRedirectUri(),
|
||||
'auth_code_id' => $authCode->getIdentifier(),
|
||||
'scopes' => $authCode->getScopes(),
|
||||
'user_id' => $authCode->getUserIdentifier(),
|
||||
'expire_time' => (new \DateTime())->add($this->authCodeTTL)->format('U'),
|
||||
'code_challenge' => $authorizationRequest->getCodeChallenge(),
|
||||
'code_challenge_method ' => $authorizationRequest->getCodeChallengeMethod(),
|
||||
]
|
||||
)
|
||||
),
|
||||
'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(),
|
||||
]
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@@ -8,6 +8,7 @@
|
||||
*
|
||||
* @link https://github.com/thephpleague/oauth2-server
|
||||
*/
|
||||
|
||||
namespace League\OAuth2\Server\Grant;
|
||||
|
||||
use League\OAuth2\Server\ResponseTypes\ResponseTypeInterface;
|
||||
@@ -21,20 +22,20 @@ class ClientCredentialsGrant extends AbstractGrant
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function respondToRequest(
|
||||
public function respondToAccessTokenRequest(
|
||||
ServerRequestInterface $request,
|
||||
ResponseTypeInterface $responseType,
|
||||
\DateInterval $accessTokenTTL
|
||||
) {
|
||||
// Validate request
|
||||
$client = $this->validateClient($request);
|
||||
$scopes = $this->validateScopes($this->getRequestParameter('scope', $request), $client);
|
||||
$scopes = $this->validateScopes($this->getRequestParameter('scope', $request));
|
||||
|
||||
// Finalize the requested scopes
|
||||
$scopes = $this->scopeRepository->finalizeScopes($scopes, $this->getIdentifier(), $client);
|
||||
|
||||
// Issue and persist access token
|
||||
$accessToken = $this->issueAccessToken($accessTokenTTL, $client, $client->getIdentifier(), $scopes);
|
||||
$accessToken = $this->issueAccessToken($accessTokenTTL, $client, null, $scopes);
|
||||
|
||||
// Inject access token into response type
|
||||
$responseType->setAccessToken($accessToken);
|
||||
|
@@ -8,12 +8,15 @@
|
||||
*
|
||||
* @link https://github.com/thephpleague/oauth2-server
|
||||
*/
|
||||
|
||||
namespace League\OAuth2\Server\Grant;
|
||||
|
||||
use League\Event\EmitterAwareInterface;
|
||||
use League\OAuth2\Server\CryptKey;
|
||||
use League\OAuth2\Server\Repositories\AccessTokenRepositoryInterface;
|
||||
use League\OAuth2\Server\Repositories\ClientRepositoryInterface;
|
||||
use League\OAuth2\Server\Repositories\ScopeRepositoryInterface;
|
||||
use League\OAuth2\Server\RequestTypes\AuthorizationRequest;
|
||||
use League\OAuth2\Server\ResponseTypes\ResponseTypeInterface;
|
||||
use Psr\Http\Message\ServerRequestInterface;
|
||||
|
||||
@@ -39,64 +42,94 @@ interface GrantTypeInterface extends EmitterAwareInterface
|
||||
/**
|
||||
* Respond to an incoming request.
|
||||
*
|
||||
* @param \Psr\Http\Message\ServerRequestInterface $request
|
||||
* @param \League\OAuth2\Server\ResponseTypes\ResponseTypeInterface $responseType
|
||||
* @param \DateInterval $accessTokenTTL
|
||||
* @param ServerRequestInterface $request
|
||||
* @param ResponseTypeInterface $responseType
|
||||
* @param \DateInterval $accessTokenTTL
|
||||
*
|
||||
* @return \League\OAuth2\Server\ResponseTypes\ResponseTypeInterface
|
||||
* @return ResponseTypeInterface
|
||||
*/
|
||||
public function respondToRequest(
|
||||
public function respondToAccessTokenRequest(
|
||||
ServerRequestInterface $request,
|
||||
ResponseTypeInterface $responseType,
|
||||
\DateInterval $accessTokenTTL
|
||||
);
|
||||
|
||||
/**
|
||||
* The grant type should return true if it is able to response to an authorization request
|
||||
*
|
||||
* @param ServerRequestInterface $request
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function canRespondToAuthorizationRequest(ServerRequestInterface $request);
|
||||
|
||||
/**
|
||||
* If the grant can respond to an authorization request this method should be called to validate the parameters of
|
||||
* the request.
|
||||
*
|
||||
* If the validation is successful an AuthorizationRequest object will be returned. This object can be safely
|
||||
* serialized in a user's session, and can be used during user authentication and authorization.
|
||||
*
|
||||
* @param ServerRequestInterface $request
|
||||
*
|
||||
* @return AuthorizationRequest
|
||||
*/
|
||||
public function validateAuthorizationRequest(ServerRequestInterface $request);
|
||||
|
||||
/**
|
||||
* Once a user has authenticated and authorized the client the grant can complete the authorization request.
|
||||
* The AuthorizationRequest object's $userId property must be set to the authenticated user and the
|
||||
* $authorizationApproved property must reflect their desire to authorize or deny the client.
|
||||
*
|
||||
* @param AuthorizationRequest $authorizationRequest
|
||||
*
|
||||
* @return ResponseTypeInterface
|
||||
*/
|
||||
public function completeAuthorizationRequest(AuthorizationRequest $authorizationRequest);
|
||||
|
||||
/**
|
||||
* The grant type should return true if it is able to respond to this request.
|
||||
*
|
||||
* For example most grant types will check that the $_POST['grant_type'] property matches it's identifier property.
|
||||
*
|
||||
* Some grants, such as the authorization code grant can respond to multiple requests
|
||||
* - i.e. a client requesting an authorization code and requesting an access token
|
||||
*
|
||||
* @param \Psr\Http\Message\ServerRequestInterface $request
|
||||
* @param ServerRequestInterface $request
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function canRespondToRequest(ServerRequestInterface $request);
|
||||
public function canRespondToAccessTokenRequest(ServerRequestInterface $request);
|
||||
|
||||
/**
|
||||
* Set the client repository.
|
||||
*
|
||||
* @param \League\OAuth2\Server\Repositories\ClientRepositoryInterface $clientRepository
|
||||
* @param ClientRepositoryInterface $clientRepository
|
||||
*/
|
||||
public function setClientRepository(ClientRepositoryInterface $clientRepository);
|
||||
|
||||
/**
|
||||
* Set the access token repository.
|
||||
*
|
||||
* @param \League\OAuth2\Server\Repositories\AccessTokenRepositoryInterface $accessTokenRepository
|
||||
* @param AccessTokenRepositoryInterface $accessTokenRepository
|
||||
*/
|
||||
public function setAccessTokenRepository(AccessTokenRepositoryInterface $accessTokenRepository);
|
||||
|
||||
/**
|
||||
* Set the scope repository.
|
||||
*
|
||||
* @param \League\OAuth2\Server\Repositories\ScopeRepositoryInterface $scopeRepository
|
||||
* @param ScopeRepositoryInterface $scopeRepository
|
||||
*/
|
||||
public function setScopeRepository(ScopeRepositoryInterface $scopeRepository);
|
||||
|
||||
/**
|
||||
* Set the path to the private key.
|
||||
*
|
||||
* @param string $privateKeyPath
|
||||
* @param CryptKey $privateKey
|
||||
*/
|
||||
public function setPrivateKeyPath($privateKeyPath);
|
||||
public function setPrivateKey(CryptKey $privateKey);
|
||||
|
||||
/**
|
||||
* Set the path to the public key.
|
||||
*
|
||||
* @param string $publicKeyPath
|
||||
* @param CryptKey $publicKey
|
||||
*/
|
||||
public function setPublicKeyPath($publicKeyPath);
|
||||
public function setPublicKey(CryptKey $publicKey);
|
||||
}
|
||||
|
@@ -1,38 +1,65 @@
|
||||
<?php
|
||||
/**
|
||||
* @author Alex Bilbie <hello@alexbilbie.com>
|
||||
* @copyright Copyright (c) Alex Bilbie
|
||||
* @license http://mit-license.org/
|
||||
*
|
||||
* @link https://github.com/thephpleague/oauth2-server
|
||||
*/
|
||||
|
||||
namespace League\OAuth2\Server\Grant;
|
||||
|
||||
use League\OAuth2\Server\Entities\Interfaces\ClientEntityInterface;
|
||||
use League\OAuth2\Server\Entities\Interfaces\UserEntityInterface;
|
||||
use League\OAuth2\Server\Entities\ClientEntityInterface;
|
||||
use League\OAuth2\Server\Entities\UserEntityInterface;
|
||||
use League\OAuth2\Server\Exception\OAuthServerException;
|
||||
use League\OAuth2\Server\Repositories\UserRepositoryInterface;
|
||||
use League\OAuth2\Server\Repositories\RefreshTokenRepositoryInterface;
|
||||
use League\OAuth2\Server\RequestEvent;
|
||||
use League\OAuth2\Server\ResponseTypes\HtmlResponse;
|
||||
use League\OAuth2\Server\RequestTypes\AuthorizationRequest;
|
||||
use League\OAuth2\Server\ResponseTypes\RedirectResponse;
|
||||
use League\OAuth2\Server\ResponseTypes\ResponseTypeInterface;
|
||||
use League\OAuth2\Server\TemplateRenderer\RendererInterface;
|
||||
use Psr\Http\Message\ServerRequestInterface;
|
||||
|
||||
class ImplicitGrant extends AbstractAuthorizeGrant
|
||||
{
|
||||
/**
|
||||
* @param \League\OAuth2\Server\Repositories\UserRepositoryInterface $userRepository
|
||||
* @param \League\OAuth2\Server\TemplateRenderer\RendererInterface|null $templateRenderer
|
||||
* @var \DateInterval
|
||||
*/
|
||||
public function __construct(UserRepositoryInterface $userRepository, RendererInterface $templateRenderer = null)
|
||||
private $accessTokenTTL;
|
||||
|
||||
/**
|
||||
* @param \DateInterval $accessTokenTTL
|
||||
*/
|
||||
public function __construct(\DateInterval $accessTokenTTL)
|
||||
{
|
||||
$this->setUserRepository($userRepository);
|
||||
$this->refreshTokenTTL = new \DateInterval('P1M');
|
||||
$this->templateRenderer = $templateRenderer;
|
||||
$this->accessTokenTTL = $accessTokenTTL;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \DateInterval $refreshTokenTTL
|
||||
*
|
||||
* @throw \LogicException
|
||||
*/
|
||||
public function setRefreshTokenTTL(\DateInterval $refreshTokenTTL)
|
||||
{
|
||||
throw new \LogicException('The Implicit Grant does not return refresh tokens');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param RefreshTokenRepositoryInterface $refreshTokenRepository
|
||||
*
|
||||
* @throw \LogicException
|
||||
*/
|
||||
public function setRefreshTokenRepository(RefreshTokenRepositoryInterface $refreshTokenRepository)
|
||||
{
|
||||
throw new \LogicException('The Implicit Grant does not return refresh tokens');
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function canRespondToRequest(ServerRequestInterface $request)
|
||||
public function canRespondToAccessTokenRequest(ServerRequestInterface $request)
|
||||
{
|
||||
return (array_key_exists('response_type', $request->getQueryParams())
|
||||
&& $request->getQueryParams()['response_type'] === 'token');
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -46,13 +73,39 @@ class ImplicitGrant extends AbstractAuthorizeGrant
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
* Respond to an incoming request.
|
||||
*
|
||||
* @param ServerRequestInterface $request
|
||||
* @param ResponseTypeInterface $responseType
|
||||
* @param \DateInterval $accessTokenTTL
|
||||
*
|
||||
* @return ResponseTypeInterface
|
||||
*/
|
||||
public function respondToRequest(
|
||||
public function respondToAccessTokenRequest(
|
||||
ServerRequestInterface $request,
|
||||
ResponseTypeInterface $responseType,
|
||||
\DateInterval $accessTokenTTL
|
||||
) {
|
||||
throw new \LogicException('This grant does not used this method');
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function canRespondToAuthorizationRequest(ServerRequestInterface $request)
|
||||
{
|
||||
return (
|
||||
array_key_exists('response_type', $request->getQueryParams())
|
||||
&& $request->getQueryParams()['response_type'] === 'token'
|
||||
&& isset($request->getQueryParams()['client_id'])
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function validateAuthorizationRequest(ServerRequestInterface $request)
|
||||
{
|
||||
$clientId = $this->getQueryStringParameter(
|
||||
'client_id',
|
||||
$request,
|
||||
@@ -64,148 +117,93 @@ class ImplicitGrant extends AbstractAuthorizeGrant
|
||||
|
||||
$client = $this->clientRepository->getClientEntity(
|
||||
$clientId,
|
||||
$this->getIdentifier()
|
||||
$this->getIdentifier(),
|
||||
null,
|
||||
false
|
||||
);
|
||||
|
||||
if ($client instanceof ClientEntityInterface === false) {
|
||||
$this->getEmitter()->emit(new RequestEvent('client.authentication.failed', $request));
|
||||
$this->getEmitter()->emit(new RequestEvent(RequestEvent::CLIENT_AUTHENTICATION_FAILED, $request));
|
||||
throw OAuthServerException::invalidClient();
|
||||
}
|
||||
|
||||
$redirectUriParameter = $this->getQueryStringParameter('redirect_uri', $request, $client->getRedirectUri());
|
||||
if ($redirectUriParameter !== $client->getRedirectUri()) {
|
||||
$this->getEmitter()->emit(new RequestEvent('client.authentication.failed', $request));
|
||||
throw OAuthServerException::invalidClient();
|
||||
$redirectUri = $this->getQueryStringParameter('redirect_uri', $request);
|
||||
if ($redirectUri !== null) {
|
||||
if (
|
||||
is_string($client->getRedirectUri())
|
||||
&& (strcmp($client->getRedirectUri(), $redirectUri) !== 0)
|
||||
) {
|
||||
$this->getEmitter()->emit(new RequestEvent(RequestEvent::CLIENT_AUTHENTICATION_FAILED, $request));
|
||||
throw OAuthServerException::invalidClient();
|
||||
} elseif (
|
||||
is_array($client->getRedirectUri())
|
||||
&& in_array($redirectUri, $client->getRedirectUri()) === false
|
||||
) {
|
||||
$this->getEmitter()->emit(new RequestEvent(RequestEvent::CLIENT_AUTHENTICATION_FAILED, $request));
|
||||
throw OAuthServerException::invalidClient();
|
||||
}
|
||||
}
|
||||
|
||||
$scopes = $this->validateScopes(
|
||||
$this->getQueryStringParameter('scope', $request),
|
||||
$client,
|
||||
$client->getRedirectUri()
|
||||
is_array($client->getRedirectUri())
|
||||
? $client->getRedirectUri()[0]
|
||||
: $client->getRedirectUri()
|
||||
);
|
||||
|
||||
$postbackUri = sprintf(
|
||||
'//%s%s',
|
||||
$request->getServerParams()['HTTP_HOST'],
|
||||
$request->getServerParams()['REQUEST_URI']
|
||||
// Finalize the requested scopes
|
||||
$scopes = $this->scopeRepository->finalizeScopes(
|
||||
$scopes,
|
||||
$this->getIdentifier(),
|
||||
$client
|
||||
);
|
||||
|
||||
$userId = null;
|
||||
$userHasApprovedClient = null;
|
||||
if ($this->getRequestParameter('action', $request, null) !== null) {
|
||||
$userHasApprovedClient = ($this->getRequestParameter('action', $request) === 'approve');
|
||||
}
|
||||
|
||||
// Check if the user has been authenticated
|
||||
$oauthCookie = $this->getCookieParameter('oauth_authorize_request', $request, null);
|
||||
if ($oauthCookie !== null) {
|
||||
try {
|
||||
$oauthCookiePayload = json_decode($this->decrypt($oauthCookie));
|
||||
if (is_object($oauthCookiePayload)) {
|
||||
$userId = $oauthCookiePayload->user_id;
|
||||
}
|
||||
} catch (\LogicException $e) {
|
||||
throw OAuthServerException::serverError($e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
// The username + password might be available in $_POST
|
||||
$usernameParameter = $this->getRequestParameter('username', $request, null);
|
||||
$passwordParameter = $this->getRequestParameter('password', $request, null);
|
||||
|
||||
$loginError = null;
|
||||
|
||||
// Assert if the user has logged in already
|
||||
if ($userId === null && $usernameParameter !== null && $passwordParameter !== null) {
|
||||
$userEntity = $this->userRepository->getUserEntityByUserCredentials(
|
||||
$usernameParameter,
|
||||
$passwordParameter,
|
||||
$this->getIdentifier(),
|
||||
$client
|
||||
);
|
||||
|
||||
if ($userEntity instanceof UserEntityInterface) {
|
||||
$userId = $userEntity->getIdentifier();
|
||||
} else {
|
||||
$loginError = 'Incorrect username or password';
|
||||
}
|
||||
}
|
||||
|
||||
// The user hasn't logged in yet so show a login form
|
||||
if ($userId === null) {
|
||||
$html = $this->getTemplateRenderer()->renderLogin([
|
||||
'error' => $loginError,
|
||||
'postback_uri' => $this->makeRedirectUri(
|
||||
$postbackUri,
|
||||
$request->getQueryParams()
|
||||
),
|
||||
]);
|
||||
|
||||
$htmlResponse = new HtmlResponse($this->accessTokenRepository);
|
||||
$htmlResponse->setStatusCode(403);
|
||||
$htmlResponse->setHtml($html);
|
||||
|
||||
return $htmlResponse;
|
||||
}
|
||||
|
||||
// The user hasn't approved the client yet so show an authorize form
|
||||
if ($userId !== null && $userHasApprovedClient === null) {
|
||||
$html = $this->getTemplateRenderer()->renderAuthorize([
|
||||
'client' => $client,
|
||||
'scopes' => $scopes,
|
||||
'postback_uri' => $this->makeRedirectUri(
|
||||
$postbackUri,
|
||||
$request->getQueryParams()
|
||||
),
|
||||
]);
|
||||
|
||||
$htmlResponse = new HtmlResponse($this->accessTokenRepository);
|
||||
$htmlResponse->setStatusCode(200);
|
||||
$htmlResponse->setHtml($html);
|
||||
$htmlResponse->setHeader('set-cookie', sprintf(
|
||||
'oauth_authorize_request=%s; Expires=%s',
|
||||
urlencode($this->encrypt(
|
||||
json_encode([
|
||||
'user_id' => $userId,
|
||||
])
|
||||
)),
|
||||
(new \DateTime())->add(new \DateInterval('PT5M'))->format('D, d M Y H:i:s e')
|
||||
));
|
||||
|
||||
return $htmlResponse;
|
||||
}
|
||||
|
||||
// The user has either approved or denied the client, so redirect them back
|
||||
$redirectUri = $client->getRedirectUri();
|
||||
$redirectPayload = [];
|
||||
|
||||
$stateParameter = $this->getQueryStringParameter('state', $request);
|
||||
if ($stateParameter !== null) {
|
||||
$redirectPayload['state'] = $stateParameter;
|
||||
|
||||
$authorizationRequest = new AuthorizationRequest();
|
||||
$authorizationRequest->setGrantTypeId($this->getIdentifier());
|
||||
$authorizationRequest->setClient($client);
|
||||
$authorizationRequest->setRedirectUri($redirectUri);
|
||||
$authorizationRequest->setState($stateParameter);
|
||||
$authorizationRequest->setScopes($scopes);
|
||||
|
||||
return $authorizationRequest;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function completeAuthorizationRequest(AuthorizationRequest $authorizationRequest)
|
||||
{
|
||||
if ($authorizationRequest->getUser() instanceof UserEntityInterface === false) {
|
||||
throw new \LogicException('An instance of UserEntityInterface should be set on the AuthorizationRequest');
|
||||
}
|
||||
|
||||
// THe user approved the client, redirect them back with an access token
|
||||
if ($userHasApprovedClient === true) {
|
||||
|
||||
// Finalize the requested scopes
|
||||
$scopes = $this->scopeRepository->finalizeScopes($scopes, $this->getIdentifier(), $client, $userId);
|
||||
$finalRedirectUri = ($authorizationRequest->getRedirectUri() === null)
|
||||
? is_array($authorizationRequest->getClient()->getRedirectUri())
|
||||
? $authorizationRequest->getClient()->getRedirectUri()[0]
|
||||
: $authorizationRequest->getClient()->getRedirectUri()
|
||||
: $authorizationRequest->getRedirectUri();
|
||||
|
||||
// The user approved the client, redirect them back with an access token
|
||||
if ($authorizationRequest->isAuthorizationApproved() === true) {
|
||||
$accessToken = $this->issueAccessToken(
|
||||
$accessTokenTTL,
|
||||
$client,
|
||||
$userId,
|
||||
$scopes
|
||||
$this->accessTokenTTL,
|
||||
$authorizationRequest->getClient(),
|
||||
$authorizationRequest->getUser()->getIdentifier(),
|
||||
$authorizationRequest->getScopes()
|
||||
);
|
||||
|
||||
$redirectPayload['access_token'] = (string) $accessToken->convertToJWT($this->privateKeyPath);
|
||||
$redirectPayload['token_type'] = 'bearer';
|
||||
$redirectPayload['expires_in'] = time() - $accessToken->getExpiryDateTime()->getTimestamp();
|
||||
|
||||
$response = new RedirectResponse($this->accessTokenRepository);
|
||||
$response = new RedirectResponse();
|
||||
$response->setRedirectUri(
|
||||
$this->makeRedirectUri(
|
||||
$redirectUri,
|
||||
$redirectPayload,
|
||||
$finalRedirectUri,
|
||||
[
|
||||
'access_token' => (string) $accessToken->convertToJWT($this->privateKey),
|
||||
'token_type' => 'bearer',
|
||||
'expires_in' => $accessToken->getExpiryDateTime()->getTimestamp() - (new \DateTime())->getTimestamp(),
|
||||
'state' => $authorizationRequest->getState(),
|
||||
],
|
||||
'#'
|
||||
)
|
||||
);
|
||||
@@ -214,6 +212,14 @@ class ImplicitGrant extends AbstractAuthorizeGrant
|
||||
}
|
||||
|
||||
// The user denied the client, redirect them back with an error
|
||||
throw OAuthServerException::accessDenied('The user denied the request', (string) $redirectUri);
|
||||
throw OAuthServerException::accessDenied(
|
||||
'The user denied the request',
|
||||
$this->makeRedirectUri(
|
||||
$finalRedirectUri,
|
||||
[
|
||||
'state' => $authorizationRequest->getState(),
|
||||
]
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@@ -8,10 +8,11 @@
|
||||
*
|
||||
* @link https://github.com/thephpleague/oauth2-server
|
||||
*/
|
||||
|
||||
namespace League\OAuth2\Server\Grant;
|
||||
|
||||
use League\OAuth2\Server\Entities\Interfaces\ClientEntityInterface;
|
||||
use League\OAuth2\Server\Entities\Interfaces\UserEntityInterface;
|
||||
use League\OAuth2\Server\Entities\ClientEntityInterface;
|
||||
use League\OAuth2\Server\Entities\UserEntityInterface;
|
||||
use League\OAuth2\Server\Exception\OAuthServerException;
|
||||
use League\OAuth2\Server\Repositories\RefreshTokenRepositoryInterface;
|
||||
use League\OAuth2\Server\Repositories\UserRepositoryInterface;
|
||||
@@ -25,8 +26,8 @@ use Psr\Http\Message\ServerRequestInterface;
|
||||
class PasswordGrant extends AbstractGrant
|
||||
{
|
||||
/**
|
||||
* @param \League\OAuth2\Server\Repositories\UserRepositoryInterface $userRepository
|
||||
* @param \League\OAuth2\Server\Repositories\RefreshTokenRepositoryInterface $refreshTokenRepository
|
||||
* @param UserRepositoryInterface $userRepository
|
||||
* @param RefreshTokenRepositoryInterface $refreshTokenRepository
|
||||
*/
|
||||
public function __construct(
|
||||
UserRepositoryInterface $userRepository,
|
||||
@@ -41,14 +42,14 @@ class PasswordGrant extends AbstractGrant
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function respondToRequest(
|
||||
public function respondToAccessTokenRequest(
|
||||
ServerRequestInterface $request,
|
||||
ResponseTypeInterface $responseType,
|
||||
\DateInterval $accessTokenTTL
|
||||
) {
|
||||
// Validate request
|
||||
$client = $this->validateClient($request);
|
||||
$scopes = $this->validateScopes($this->getRequestParameter('scope', $request), $client);
|
||||
$scopes = $this->validateScopes($this->getRequestParameter('scope', $request));
|
||||
$user = $this->validateUser($request, $client);
|
||||
|
||||
// Finalize the requested scopes
|
||||
@@ -66,23 +67,23 @@ class PasswordGrant extends AbstractGrant
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \Psr\Http\Message\ServerRequestInterface $request
|
||||
* @param \League\OAuth2\Server\Entities\Interfaces\ClientEntityInterface $client
|
||||
* @param ServerRequestInterface $request
|
||||
* @param ClientEntityInterface $client
|
||||
*
|
||||
* @throws \League\OAuth2\Server\Exception\OAuthServerException
|
||||
* @throws OAuthServerException
|
||||
*
|
||||
* @return \League\OAuth2\Server\Entities\Interfaces\UserEntityInterface
|
||||
* @return UserEntityInterface
|
||||
*/
|
||||
protected function validateUser(ServerRequestInterface $request, ClientEntityInterface $client)
|
||||
{
|
||||
$username = $this->getRequestParameter('username', $request);
|
||||
if (is_null($username)) {
|
||||
throw OAuthServerException::invalidRequest('username', '`%s` parameter is missing');
|
||||
throw OAuthServerException::invalidRequest('username');
|
||||
}
|
||||
|
||||
$password = $this->getRequestParameter('password', $request);
|
||||
if (is_null($password)) {
|
||||
throw OAuthServerException::invalidRequest('password', '`%s` parameter is missing');
|
||||
throw OAuthServerException::invalidRequest('password');
|
||||
}
|
||||
|
||||
$user = $this->userRepository->getUserEntityByUserCredentials(
|
||||
@@ -91,8 +92,8 @@ class PasswordGrant extends AbstractGrant
|
||||
$this->getIdentifier(),
|
||||
$client
|
||||
);
|
||||
if (!$user instanceof UserEntityInterface) {
|
||||
$this->getEmitter()->emit(new RequestEvent('user.authentication.failed', $request));
|
||||
if ($user instanceof UserEntityInterface === false) {
|
||||
$this->getEmitter()->emit(new RequestEvent(RequestEvent::USER_AUTHENTICATION_FAILED, $request));
|
||||
|
||||
throw OAuthServerException::invalidCredentials();
|
||||
}
|
||||
|
@@ -8,8 +8,10 @@
|
||||
*
|
||||
* @link https://github.com/thephpleague/oauth2-server
|
||||
*/
|
||||
|
||||
namespace League\OAuth2\Server\Grant;
|
||||
|
||||
use League\OAuth2\Server\Entities\ScopeEntityInterface;
|
||||
use League\OAuth2\Server\Exception\OAuthServerException;
|
||||
use League\OAuth2\Server\Repositories\RefreshTokenRepositoryInterface;
|
||||
use League\OAuth2\Server\RequestEvent;
|
||||
@@ -22,7 +24,7 @@ use Psr\Http\Message\ServerRequestInterface;
|
||||
class RefreshTokenGrant extends AbstractGrant
|
||||
{
|
||||
/**
|
||||
* @param \League\OAuth2\Server\Repositories\RefreshTokenRepositoryInterface $refreshTokenRepository
|
||||
* @param RefreshTokenRepositoryInterface $refreshTokenRepository
|
||||
*/
|
||||
public function __construct(RefreshTokenRepositoryInterface $refreshTokenRepository)
|
||||
{
|
||||
@@ -34,7 +36,7 @@ class RefreshTokenGrant extends AbstractGrant
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function respondToRequest(
|
||||
public function respondToAccessTokenRequest(
|
||||
ServerRequestInterface $request,
|
||||
ResponseTypeInterface $responseType,
|
||||
\DateInterval $accessTokenTTL
|
||||
@@ -42,14 +44,14 @@ class RefreshTokenGrant extends AbstractGrant
|
||||
// Validate request
|
||||
$client = $this->validateClient($request);
|
||||
$oldRefreshToken = $this->validateOldRefreshToken($request, $client->getIdentifier());
|
||||
$scopes = $this->validateScopes($this->getRequestParameter('scope', $request), $client);
|
||||
$scopes = $this->validateScopes($this->getRequestParameter('scope', $request));
|
||||
|
||||
// If no new scopes are requested then give the access token the original session scopes
|
||||
if (count($scopes) === 0) {
|
||||
$scopes = array_map(function ($scopeId) use ($client) {
|
||||
$scope = $this->scopeRepository->getScopeEntityByIdentifier($scopeId);
|
||||
|
||||
if (!$scope) {
|
||||
if ($scope instanceof ScopeEntityInterface === false) {
|
||||
// @codeCoverageIgnoreStart
|
||||
throw OAuthServerException::invalidScope($scopeId);
|
||||
// @codeCoverageIgnoreEnd
|
||||
@@ -83,10 +85,10 @@ class RefreshTokenGrant extends AbstractGrant
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \Psr\Http\Message\ServerRequestInterface $request
|
||||
* @param string $clientId
|
||||
* @param ServerRequestInterface $request
|
||||
* @param string $clientId
|
||||
*
|
||||
* @throws \League\OAuth2\Server\Exception\OAuthServerException
|
||||
* @throws OAuthServerException
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
@@ -101,17 +103,13 @@ class RefreshTokenGrant extends AbstractGrant
|
||||
try {
|
||||
$refreshToken = $this->decrypt($encryptedRefreshToken);
|
||||
} catch (\LogicException $e) {
|
||||
throw OAuthServerException::invalidRefreshToken('Cannot parse refresh token: ' . $e->getMessage());
|
||||
throw OAuthServerException::invalidRefreshToken('Cannot decrypt the refresh token');
|
||||
}
|
||||
|
||||
$refreshTokenData = json_decode($refreshToken, true);
|
||||
if ($refreshTokenData['client_id'] !== $clientId) {
|
||||
$this->getEmitter()->emit(new RequestEvent('refresh_token.client.failed', $request));
|
||||
throw OAuthServerException::invalidRefreshToken(
|
||||
'Token is not linked to client,' .
|
||||
' got: ' . $clientId .
|
||||
' expected: ' . $refreshTokenData['client_id']
|
||||
);
|
||||
$this->getEmitter()->emit(new RequestEvent(RequestEvent::REFRESH_TOKEN_CLIENT_FAILED, $request));
|
||||
throw OAuthServerException::invalidRefreshToken('Token is not linked to client');
|
||||
}
|
||||
|
||||
if ($refreshTokenData['expire_time'] < time()) {
|
||||
|
@@ -1,51 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace League\OAuth2\Server\Middleware;
|
||||
|
||||
use League\OAuth2\Server\Exception\OAuthServerException;
|
||||
use League\OAuth2\Server\Server;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
use Psr\Http\Message\ServerRequestInterface;
|
||||
|
||||
class AuthenticationServerMiddleware
|
||||
{
|
||||
/**
|
||||
* @var \League\OAuth2\Server\Server
|
||||
*/
|
||||
private $server;
|
||||
|
||||
/**
|
||||
* AuthenticationServerMiddleware constructor.
|
||||
*
|
||||
* @param \League\OAuth2\Server\Server $server
|
||||
*/
|
||||
public function __construct(Server $server)
|
||||
{
|
||||
$this->server = $server;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \Psr\Http\Message\ServerRequestInterface $request
|
||||
* @param \Psr\Http\Message\ResponseInterface $response
|
||||
* @param callable $next
|
||||
*
|
||||
* @return \Psr\Http\Message\ResponseInterface
|
||||
*/
|
||||
public function __invoke(ServerRequestInterface $request, ResponseInterface $response, callable $next)
|
||||
{
|
||||
try {
|
||||
$response = $this->server->respondToRequest($request, $response);
|
||||
} catch (OAuthServerException $exception) {
|
||||
return $exception->generateHttpResponse($response);
|
||||
// @codeCoverageIgnoreStart
|
||||
} catch (\Exception $exception) {
|
||||
$response->getBody()->write($exception->getMessage());
|
||||
|
||||
return $response->withStatus(500);
|
||||
// @codeCoverageIgnoreEnd
|
||||
}
|
||||
|
||||
// Pass the request and response on to the next responder in the chain
|
||||
return $next($request, $response);
|
||||
}
|
||||
}
|
55
src/Middleware/AuthorizationServerMiddleware.php
Normal file
55
src/Middleware/AuthorizationServerMiddleware.php
Normal file
@@ -0,0 +1,55 @@
|
||||
<?php
|
||||
/**
|
||||
* @author Alex Bilbie <hello@alexbilbie.com>
|
||||
* @copyright Copyright (c) Alex Bilbie
|
||||
* @license http://mit-license.org/
|
||||
*
|
||||
* @link https://github.com/thephpleague/oauth2-server
|
||||
*/
|
||||
|
||||
namespace League\OAuth2\Server\Middleware;
|
||||
|
||||
use League\OAuth2\Server\AuthorizationServer;
|
||||
use League\OAuth2\Server\Exception\OAuthServerException;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
use Psr\Http\Message\ServerRequestInterface;
|
||||
|
||||
class AuthorizationServerMiddleware
|
||||
{
|
||||
/**
|
||||
* @var AuthorizationServer
|
||||
*/
|
||||
private $server;
|
||||
|
||||
/**
|
||||
* @param AuthorizationServer $server
|
||||
*/
|
||||
public function __construct(AuthorizationServer $server)
|
||||
{
|
||||
$this->server = $server;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ServerRequestInterface $request
|
||||
* @param ResponseInterface $response
|
||||
* @param callable $next
|
||||
*
|
||||
* @return ResponseInterface
|
||||
*/
|
||||
public function __invoke(ServerRequestInterface $request, ResponseInterface $response, callable $next)
|
||||
{
|
||||
try {
|
||||
$response = $this->server->respondToAccessTokenRequest($request, $response);
|
||||
} catch (OAuthServerException $exception) {
|
||||
return $exception->generateHttpResponse($response);
|
||||
// @codeCoverageIgnoreStart
|
||||
} catch (\Exception $exception) {
|
||||
return (new OAuthServerException($exception->getMessage(), 0, 'unknown_error', 500))
|
||||
->generateHttpResponse($response);
|
||||
// @codeCoverageIgnoreEnd
|
||||
}
|
||||
|
||||
// Pass the request and response on to the next responder in the chain
|
||||
return $next($request, $response);
|
||||
}
|
||||
}
|
@@ -1,33 +1,38 @@
|
||||
<?php
|
||||
/**
|
||||
* @author Alex Bilbie <hello@alexbilbie.com>
|
||||
* @copyright Copyright (c) Alex Bilbie
|
||||
* @license http://mit-license.org/
|
||||
*
|
||||
* @link https://github.com/thephpleague/oauth2-server
|
||||
*/
|
||||
|
||||
namespace League\OAuth2\Server\Middleware;
|
||||
|
||||
use League\OAuth2\Server\Exception\OAuthServerException;
|
||||
use League\OAuth2\Server\Server;
|
||||
use League\OAuth2\Server\ResourceServer;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
use Psr\Http\Message\ServerRequestInterface;
|
||||
|
||||
class ResourceServerMiddleware
|
||||
{
|
||||
/**
|
||||
* @var \League\OAuth2\Server\Server
|
||||
* @var ResourceServer
|
||||
*/
|
||||
private $server;
|
||||
|
||||
/**
|
||||
* ResourceServerMiddleware constructor.
|
||||
*
|
||||
* @param \League\OAuth2\Server\Server $server
|
||||
* @param ResourceServer $server
|
||||
*/
|
||||
public function __construct(Server $server)
|
||||
public function __construct(ResourceServer $server)
|
||||
{
|
||||
$this->server = $server;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \Psr\Http\Message\ServerRequestInterface $request
|
||||
* @param \Psr\Http\Message\ResponseInterface $response
|
||||
* @param callable $next
|
||||
* @param ServerRequestInterface $request
|
||||
* @param ResponseInterface $response
|
||||
* @param callable $next
|
||||
*
|
||||
* @return \Psr\Http\Message\ResponseInterface
|
||||
*/
|
||||
@@ -39,9 +44,8 @@ class ResourceServerMiddleware
|
||||
return $exception->generateHttpResponse($response);
|
||||
// @codeCoverageIgnoreStart
|
||||
} catch (\Exception $exception) {
|
||||
$response->getBody()->write($exception->getMessage());
|
||||
|
||||
return $response->withStatus(500);
|
||||
return (new OAuthServerException($exception->getMessage(), 0, 'unknown_error', 500))
|
||||
->generateHttpResponse($response);
|
||||
// @codeCoverageIgnoreEnd
|
||||
}
|
||||
|
||||
|
@@ -1,26 +1,38 @@
|
||||
<?php
|
||||
/**
|
||||
* OAuth 2.0 Access token storage interface.
|
||||
*
|
||||
* @author Alex Bilbie <hello@alexbilbie.com>
|
||||
* @copyright Copyright (c) Alex Bilbie
|
||||
* @license http://mit-license.org/
|
||||
*
|
||||
* @link https://github.com/thephpleague/oauth2-server
|
||||
*/
|
||||
|
||||
namespace League\OAuth2\Server\Repositories;
|
||||
|
||||
use League\OAuth2\Server\Entities\Interfaces\AccessTokenEntityInterface;
|
||||
use League\OAuth2\Server\Entities\AccessTokenEntityInterface;
|
||||
use League\OAuth2\Server\Entities\ClientEntityInterface;
|
||||
use League\OAuth2\Server\Entities\ScopeEntityInterface;
|
||||
|
||||
/**
|
||||
* Access token interface.
|
||||
*/
|
||||
interface AccessTokenRepositoryInterface extends RepositoryInterface
|
||||
{
|
||||
/**
|
||||
* Create a new access token
|
||||
*
|
||||
* @param ClientEntityInterface $clientEntity
|
||||
* @param ScopeEntityInterface[] $scopes
|
||||
* @param mixed $userIdentifier
|
||||
*
|
||||
* @return AccessTokenEntityInterface
|
||||
*/
|
||||
public function getNewToken(ClientEntityInterface $clientEntity, array $scopes, $userIdentifier = null);
|
||||
|
||||
/**
|
||||
* Persists a new access token to permanent storage.
|
||||
*
|
||||
* @param \League\OAuth2\Server\Entities\Interfaces\AccessTokenEntityInterface $accessTokenEntity
|
||||
* @param AccessTokenEntityInterface $accessTokenEntity
|
||||
*/
|
||||
public function persistNewAccessToken(AccessTokenEntityInterface $accessTokenEntity);
|
||||
|
||||
|
@@ -1,26 +1,32 @@
|
||||
<?php
|
||||
/**
|
||||
* OAuth 2.0 Auth code storage interface.
|
||||
*
|
||||
* @author Alex Bilbie <hello@alexbilbie.com>
|
||||
* @copyright Copyright (c) Alex Bilbie
|
||||
* @license http://mit-license.org/
|
||||
*
|
||||
* @link https://github.com/thephpleague/oauth2-server
|
||||
*/
|
||||
|
||||
namespace League\OAuth2\Server\Repositories;
|
||||
|
||||
use League\OAuth2\Server\Entities\Interfaces\AuthCodeEntityInterface;
|
||||
use League\OAuth2\Server\Entities\AuthCodeEntityInterface;
|
||||
|
||||
/**
|
||||
* Auth code storage interface.
|
||||
*/
|
||||
interface AuthCodeRepositoryInterface extends RepositoryInterface
|
||||
{
|
||||
/**
|
||||
* Creates a new AuthCode
|
||||
*
|
||||
* @return AuthCodeEntityInterface
|
||||
*/
|
||||
public function getNewAuthCode();
|
||||
|
||||
/**
|
||||
* Persists a new auth code to permanent storage.
|
||||
*
|
||||
* @param \League\OAuth2\Server\Entities\Interfaces\AuthCodeEntityInterface $authCodeEntity
|
||||
* @param AuthCodeEntityInterface $authCodeEntity
|
||||
*/
|
||||
public function persistNewAuthCode(AuthCodeEntityInterface $authCodeEntity);
|
||||
|
||||
|
@@ -1,15 +1,16 @@
|
||||
<?php
|
||||
/**
|
||||
* OAuth 2.0 Client storage interface.
|
||||
*
|
||||
* @author Alex Bilbie <hello@alexbilbie.com>
|
||||
* @copyright Copyright (c) Alex Bilbie
|
||||
* @license http://mit-license.org/
|
||||
*
|
||||
* @link https://github.com/thephpleague/oauth2-server
|
||||
*/
|
||||
|
||||
namespace League\OAuth2\Server\Repositories;
|
||||
|
||||
use League\OAuth2\Server\Entities\ClientEntityInterface;
|
||||
|
||||
/**
|
||||
* Client storage interface.
|
||||
*/
|
||||
@@ -18,11 +19,13 @@ interface ClientRepositoryInterface extends RepositoryInterface
|
||||
/**
|
||||
* Get a client.
|
||||
*
|
||||
* @param string $clientIdentifier The client's identifier
|
||||
* @param string $grantType The grant type used
|
||||
* @param null|string $clientSecret The client's secret (if sent)
|
||||
* @param string $clientIdentifier The client's identifier
|
||||
* @param string $grantType The grant type used
|
||||
* @param null|string $clientSecret The client's secret (if sent)
|
||||
* @param bool $mustValidateSecret If true the client must attempt to validate the secret if the client
|
||||
* is confidential
|
||||
*
|
||||
* @return \League\OAuth2\Server\Entities\Interfaces\ClientEntityInterface
|
||||
* @return ClientEntityInterface
|
||||
*/
|
||||
public function getClientEntity($clientIdentifier, $grantType, $clientSecret = null);
|
||||
public function getClientEntity($clientIdentifier, $grantType, $clientSecret = null, $mustValidateSecret = true);
|
||||
}
|
||||
|
@@ -1,36 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* OAuth 2.0 MAC Token Interface.
|
||||
*
|
||||
* @author Alex Bilbie <hello@alexbilbie.com>
|
||||
* @copyright Copyright (c) Alex Bilbie
|
||||
* @license http://mit-license.org/
|
||||
*
|
||||
* @link https://github.com/thephpleague/oauth2-server
|
||||
*/
|
||||
namespace League\OAuth2\Server\Storage;
|
||||
|
||||
use League\OAuth2\Server\Repositories\RepositoryInterface;
|
||||
|
||||
/**
|
||||
* MacTokenInterface.
|
||||
*/
|
||||
interface MacTokenInterface extends RepositoryInterface
|
||||
{
|
||||
/**
|
||||
* Create a MAC key linked to an access token.
|
||||
*
|
||||
* @param string $macKey
|
||||
* @param string $accessToken
|
||||
*/
|
||||
public function persistMacTokenEntity($macKey, $accessToken);
|
||||
|
||||
/**
|
||||
* Get a MAC key by access token.
|
||||
*
|
||||
* @param string $accessToken
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getMacKeyByAccessTokenString($accessToken);
|
||||
}
|
@@ -1,26 +1,32 @@
|
||||
<?php
|
||||
/**
|
||||
* OAuth 2.0 Refresh token storage interface.
|
||||
*
|
||||
* @author Alex Bilbie <hello@alexbilbie.com>
|
||||
* @copyright Copyright (c) Alex Bilbie
|
||||
* @license http://mit-license.org/
|
||||
*
|
||||
* @link https://github.com/thephpleague/oauth2-server
|
||||
*/
|
||||
|
||||
namespace League\OAuth2\Server\Repositories;
|
||||
|
||||
use League\OAuth2\Server\Entities\Interfaces\RefreshTokenEntityInterface;
|
||||
use League\OAuth2\Server\Entities\RefreshTokenEntityInterface;
|
||||
|
||||
/**
|
||||
* Refresh token interface.
|
||||
*/
|
||||
interface RefreshTokenRepositoryInterface extends RepositoryInterface
|
||||
{
|
||||
/**
|
||||
* Creates a new refresh token
|
||||
*
|
||||
* @return RefreshTokenEntityInterface
|
||||
*/
|
||||
public function getNewRefreshToken();
|
||||
|
||||
/**
|
||||
* Create a new refresh token_name.
|
||||
*
|
||||
* @param \League\OAuth2\Server\Entities\Interfaces\RefreshTokenEntityInterface $refreshTokenEntity
|
||||
* @param RefreshTokenEntityInterface $refreshTokenEntity
|
||||
*/
|
||||
public function persistNewRefreshToken(RefreshTokenEntityInterface $refreshTokenEntity);
|
||||
|
||||
|
@@ -1,13 +1,12 @@
|
||||
<?php
|
||||
/**
|
||||
* OAuth 2.0 Repository interface.
|
||||
*
|
||||
* @author Alex Bilbie <hello@alexbilbie.com>
|
||||
* @copyright Copyright (c) Alex Bilbie
|
||||
* @license http://mit-license.org/
|
||||
*
|
||||
* @link https://github.com/thephpleague/oauth2-server
|
||||
*/
|
||||
|
||||
namespace League\OAuth2\Server\Repositories;
|
||||
|
||||
/**
|
||||
|
@@ -1,17 +1,16 @@
|
||||
<?php
|
||||
/**
|
||||
* OAuth 2.0 Scope storage interface.
|
||||
*
|
||||
* @author Alex Bilbie <hello@alexbilbie.com>
|
||||
* @copyright Copyright (c) Alex Bilbie
|
||||
* @license http://mit-license.org/
|
||||
*
|
||||
* @link https://github.com/thephpleague/oauth2-server
|
||||
*/
|
||||
|
||||
namespace League\OAuth2\Server\Repositories;
|
||||
|
||||
use League\OAuth2\Server\Entities\Interfaces\ClientEntityInterface;
|
||||
use League\OAuth2\Server\Entities\Interfaces\ScopeEntityInterface;
|
||||
use League\OAuth2\Server\Entities\ClientEntityInterface;
|
||||
use League\OAuth2\Server\Entities\ScopeEntityInterface;
|
||||
|
||||
/**
|
||||
* Scope interface.
|
||||
@@ -23,7 +22,7 @@ interface ScopeRepositoryInterface extends RepositoryInterface
|
||||
*
|
||||
* @param string $identifier The scope identifier
|
||||
*
|
||||
* @return \League\OAuth2\Server\Entities\Interfaces\ScopeEntityInterface
|
||||
* @return ScopeEntityInterface
|
||||
*/
|
||||
public function getScopeEntityByIdentifier($identifier);
|
||||
|
||||
@@ -31,12 +30,12 @@ interface ScopeRepositoryInterface extends RepositoryInterface
|
||||
* Given a client, grant type and optional user identifier validate the set of scopes requested are valid and optionally
|
||||
* append additional scopes or remove requested scopes.
|
||||
*
|
||||
* @param ScopeEntityInterface[] $scopes
|
||||
* @param string $grantType
|
||||
* @param \League\OAuth2\Server\Entities\Interfaces\ClientEntityInterface $clientEntity
|
||||
* @param null|string $userIdentifier
|
||||
* @param ScopeEntityInterface[] $scopes
|
||||
* @param string $grantType
|
||||
* @param ClientEntityInterface $clientEntity
|
||||
* @param null|string $userIdentifier
|
||||
*
|
||||
* @return \League\OAuth2\Server\Entities\Interfaces\ScopeEntityInterface[]
|
||||
* @return ScopeEntityInterface[]
|
||||
*/
|
||||
public function finalizeScopes(
|
||||
array $scopes,
|
||||
|
@@ -1,20 +1,28 @@
|
||||
<?php
|
||||
/**
|
||||
* @author Alex Bilbie <hello@alexbilbie.com>
|
||||
* @copyright Copyright (c) Alex Bilbie
|
||||
* @license http://mit-license.org/
|
||||
*
|
||||
* @link https://github.com/thephpleague/oauth2-server
|
||||
*/
|
||||
|
||||
namespace League\OAuth2\Server\Repositories;
|
||||
|
||||
use League\OAuth2\Server\Entities\Interfaces\ClientEntityInterface;
|
||||
use League\OAuth2\Server\Entities\ClientEntityInterface;
|
||||
use League\OAuth2\Server\Entities\UserEntityInterface;
|
||||
|
||||
interface UserRepositoryInterface extends RepositoryInterface
|
||||
{
|
||||
/**
|
||||
* Get a user entity.
|
||||
*
|
||||
* @param string $username
|
||||
* @param string $password
|
||||
* @param string $grantType The grant type used
|
||||
* @param \League\OAuth2\Server\Entities\Interfaces\ClientEntityInterface $clientEntity
|
||||
* @param string $username
|
||||
* @param string $password
|
||||
* @param string $grantType The grant type used
|
||||
* @param ClientEntityInterface $clientEntity
|
||||
*
|
||||
* @return \League\OAuth2\Server\Entities\Interfaces\UserEntityInterface
|
||||
* @return UserEntityInterface
|
||||
*/
|
||||
public function getUserEntityByUserCredentials(
|
||||
$username,
|
||||
|
@@ -1,4 +1,11 @@
|
||||
<?php
|
||||
/**
|
||||
* @author Alex Bilbie <hello@alexbilbie.com>
|
||||
* @copyright Copyright (c) Alex Bilbie
|
||||
* @license http://mit-license.org/
|
||||
*
|
||||
* @link https://github.com/thephpleague/oauth2-server
|
||||
*/
|
||||
|
||||
namespace League\OAuth2\Server;
|
||||
|
||||
@@ -7,16 +14,20 @@ use Psr\Http\Message\ServerRequestInterface;
|
||||
|
||||
class RequestEvent extends Event
|
||||
{
|
||||
const CLIENT_AUTHENTICATION_FAILED = 'client.authentication.failed';
|
||||
const USER_AUTHENTICATION_FAILED = 'user.authentication.failed';
|
||||
const REFRESH_TOKEN_CLIENT_FAILED = 'refresh_token.client.failed';
|
||||
|
||||
/**
|
||||
* @var \Psr\Http\Message\ServerRequestInterface
|
||||
* @var ServerRequestInterface
|
||||
*/
|
||||
private $request;
|
||||
|
||||
/**
|
||||
* RequestEvent constructor.
|
||||
*
|
||||
* @param string $name
|
||||
* @param \Psr\Http\Message\ServerRequestInterface $request
|
||||
* @param string $name
|
||||
* @param ServerRequestInterface $request
|
||||
*/
|
||||
public function __construct($name, ServerRequestInterface $request)
|
||||
{
|
||||
@@ -26,6 +37,7 @@ class RequestEvent extends Event
|
||||
|
||||
/**
|
||||
* @return ServerRequestInterface
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public function getRequest()
|
||||
{
|
||||
|
224
src/RequestTypes/AuthorizationRequest.php
Normal file
224
src/RequestTypes/AuthorizationRequest.php
Normal file
@@ -0,0 +1,224 @@
|
||||
<?php
|
||||
/**
|
||||
* @author Alex Bilbie <hello@alexbilbie.com>
|
||||
* @copyright Copyright (c) Alex Bilbie
|
||||
* @license http://mit-license.org/
|
||||
*
|
||||
* @link https://github.com/thephpleague/oauth2-server
|
||||
*/
|
||||
|
||||
namespace League\OAuth2\Server\RequestTypes;
|
||||
|
||||
use League\OAuth2\Server\Entities\ClientEntityInterface;
|
||||
use League\OAuth2\Server\Entities\ScopeEntityInterface;
|
||||
use League\OAuth2\Server\Entities\UserEntityInterface;
|
||||
|
||||
class AuthorizationRequest
|
||||
{
|
||||
/**
|
||||
* The grant type identifier
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $grantTypeId;
|
||||
|
||||
/**
|
||||
* The client identifier
|
||||
*
|
||||
* @var ClientEntityInterface
|
||||
*/
|
||||
protected $client;
|
||||
|
||||
/**
|
||||
* The user identifier
|
||||
*
|
||||
* @var UserEntityInterface
|
||||
*/
|
||||
protected $user;
|
||||
|
||||
/**
|
||||
* An array of scope identifiers
|
||||
*
|
||||
* @var ScopeEntityInterface[]
|
||||
*/
|
||||
protected $scopes = [];
|
||||
|
||||
/**
|
||||
* Has the user authorized the authorization request
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
protected $authorizationApproved = false;
|
||||
|
||||
/**
|
||||
* The redirect URI used in the request
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $redirectUri;
|
||||
|
||||
/**
|
||||
* The state parameter on the authorization request
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $state;
|
||||
|
||||
/**
|
||||
* The code challenge (if provided)
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $codeChallenge;
|
||||
|
||||
/**
|
||||
* The code challenge method (if provided)
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $codeChallengeMethod;
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getGrantTypeId()
|
||||
{
|
||||
return $this->grantTypeId;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $grantTypeId
|
||||
*/
|
||||
public function setGrantTypeId($grantTypeId)
|
||||
{
|
||||
$this->grantTypeId = $grantTypeId;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return ClientEntityInterface
|
||||
*/
|
||||
public function getClient()
|
||||
{
|
||||
return $this->client;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ClientEntityInterface $client
|
||||
*/
|
||||
public function setClient(ClientEntityInterface $client)
|
||||
{
|
||||
$this->client = $client;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return UserEntityInterface
|
||||
*/
|
||||
public function getUser()
|
||||
{
|
||||
return $this->user;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param UserEntityInterface $user
|
||||
*/
|
||||
public function setUser(UserEntityInterface $user)
|
||||
{
|
||||
$this->user = $user;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return ScopeEntityInterface[]
|
||||
*/
|
||||
public function getScopes()
|
||||
{
|
||||
return $this->scopes;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ScopeEntityInterface[] $scopes
|
||||
*/
|
||||
public function setScopes(array $scopes)
|
||||
{
|
||||
$this->scopes = $scopes;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function isAuthorizationApproved()
|
||||
{
|
||||
return $this->authorizationApproved;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param bool $authorizationApproved
|
||||
*/
|
||||
public function setAuthorizationApproved($authorizationApproved)
|
||||
{
|
||||
$this->authorizationApproved = $authorizationApproved;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getRedirectUri()
|
||||
{
|
||||
return $this->redirectUri;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $redirectUri
|
||||
*/
|
||||
public function setRedirectUri($redirectUri)
|
||||
{
|
||||
$this->redirectUri = $redirectUri;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getState()
|
||||
{
|
||||
return $this->state;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $state
|
||||
*/
|
||||
public function setState($state)
|
||||
{
|
||||
$this->state = $state;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getCodeChallenge()
|
||||
{
|
||||
return $this->codeChallenge;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $codeChallenge
|
||||
*/
|
||||
public function setCodeChallenge($codeChallenge)
|
||||
{
|
||||
$this->codeChallenge = $codeChallenge;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getCodeChallengeMethod()
|
||||
{
|
||||
return $this->codeChallengeMethod;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $codeChallengeMethod
|
||||
*/
|
||||
public function setCodeChallengeMethod($codeChallengeMethod)
|
||||
{
|
||||
$this->codeChallengeMethod = $codeChallengeMethod;
|
||||
}
|
||||
}
|
84
src/ResourceServer.php
Normal file
84
src/ResourceServer.php
Normal 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;
|
||||
|
||||
use League\OAuth2\Server\AuthorizationValidators\AuthorizationValidatorInterface;
|
||||
use League\OAuth2\Server\AuthorizationValidators\BearerTokenValidator;
|
||||
use League\OAuth2\Server\Exception\OAuthServerException;
|
||||
use League\OAuth2\Server\Repositories\AccessTokenRepositoryInterface;
|
||||
use Psr\Http\Message\ServerRequestInterface;
|
||||
|
||||
class ResourceServer
|
||||
{
|
||||
/**
|
||||
* @var AccessTokenRepositoryInterface
|
||||
*/
|
||||
private $accessTokenRepository;
|
||||
|
||||
/**
|
||||
* @var CryptKey
|
||||
*/
|
||||
private $publicKey;
|
||||
|
||||
/**
|
||||
* @var null|AuthorizationValidatorInterface
|
||||
*/
|
||||
private $authorizationValidator;
|
||||
|
||||
/**
|
||||
* New server instance.
|
||||
*
|
||||
* @param AccessTokenRepositoryInterface $accessTokenRepository
|
||||
* @param CryptKey|string $publicKey
|
||||
* @param null|AuthorizationValidatorInterface $authorizationValidator
|
||||
*/
|
||||
public function __construct(
|
||||
AccessTokenRepositoryInterface $accessTokenRepository,
|
||||
$publicKey,
|
||||
AuthorizationValidatorInterface $authorizationValidator = null
|
||||
) {
|
||||
$this->accessTokenRepository = $accessTokenRepository;
|
||||
|
||||
if ($publicKey instanceof CryptKey === false) {
|
||||
$publicKey = new CryptKey($publicKey);
|
||||
}
|
||||
$this->publicKey = $publicKey;
|
||||
|
||||
$this->authorizationValidator = $authorizationValidator;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return AuthorizationValidatorInterface
|
||||
*/
|
||||
protected function getAuthorizationValidator()
|
||||
{
|
||||
if ($this->authorizationValidator instanceof AuthorizationValidatorInterface === false) {
|
||||
$this->authorizationValidator = new BearerTokenValidator($this->accessTokenRepository);
|
||||
}
|
||||
|
||||
$this->authorizationValidator->setPublicKey($this->publicKey);
|
||||
|
||||
return $this->authorizationValidator;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine the access token validity.
|
||||
*
|
||||
* @param ServerRequestInterface $request
|
||||
*
|
||||
* @throws OAuthServerException
|
||||
*
|
||||
* @return ServerRequestInterface
|
||||
*/
|
||||
public function validateAuthenticatedRequest(ServerRequestInterface $request)
|
||||
{
|
||||
return $this->getAuthorizationValidator()->validateAuthorization($request);
|
||||
}
|
||||
}
|
@@ -8,40 +8,27 @@
|
||||
*
|
||||
* @link https://github.com/thephpleague/oauth2-server
|
||||
*/
|
||||
|
||||
namespace League\OAuth2\Server\ResponseTypes;
|
||||
|
||||
use League\OAuth2\Server\CryptTrait;
|
||||
use League\OAuth2\Server\Entities\Interfaces\AccessTokenEntityInterface;
|
||||
use League\OAuth2\Server\Entities\Interfaces\RefreshTokenEntityInterface;
|
||||
use League\OAuth2\Server\Repositories\AccessTokenRepositoryInterface;
|
||||
use League\OAuth2\Server\Entities\AccessTokenEntityInterface;
|
||||
use League\OAuth2\Server\Entities\RefreshTokenEntityInterface;
|
||||
|
||||
abstract class AbstractResponseType implements ResponseTypeInterface
|
||||
{
|
||||
use CryptTrait;
|
||||
|
||||
/**
|
||||
* @var \League\OAuth2\Server\Entities\Interfaces\AccessTokenEntityInterface
|
||||
* @var AccessTokenEntityInterface
|
||||
*/
|
||||
protected $accessToken;
|
||||
|
||||
/**
|
||||
* @var \League\OAuth2\Server\Entities\Interfaces\RefreshTokenEntityInterface
|
||||
* @var RefreshTokenEntityInterface
|
||||
*/
|
||||
protected $refreshToken;
|
||||
|
||||
/**
|
||||
* @var \League\OAuth2\Server\Repositories\AccessTokenRepositoryInterface
|
||||
*/
|
||||
protected $accessTokenRepository;
|
||||
|
||||
/**
|
||||
* @param \League\OAuth2\Server\Repositories\AccessTokenRepositoryInterface $accessTokenRepository
|
||||
*/
|
||||
public function __construct(AccessTokenRepositoryInterface $accessTokenRepository)
|
||||
{
|
||||
$this->accessTokenRepository = $accessTokenRepository;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
|
@@ -1,6 +1,6 @@
|
||||
<?php
|
||||
/**
|
||||
* OAuth 2.0 Bearer Token Type.
|
||||
* OAuth 2.0 Bearer Token Response.
|
||||
*
|
||||
* @author Alex Bilbie <hello@alexbilbie.com>
|
||||
* @copyright Copyright (c) Alex Bilbie
|
||||
@@ -8,9 +8,11 @@
|
||||
*
|
||||
* @link https://github.com/thephpleague/oauth2-server
|
||||
*/
|
||||
|
||||
namespace League\OAuth2\Server\ResponseTypes;
|
||||
|
||||
use League\OAuth2\Server\Entities\Interfaces\RefreshTokenEntityInterface;
|
||||
use League\OAuth2\Server\Entities\AccessTokenEntityInterface;
|
||||
use League\OAuth2\Server\Entities\RefreshTokenEntityInterface;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
|
||||
class BearerTokenResponse extends AbstractResponseType
|
||||
@@ -22,7 +24,7 @@ class BearerTokenResponse extends AbstractResponseType
|
||||
{
|
||||
$expireDateTime = $this->accessToken->getExpiryDateTime()->getTimestamp();
|
||||
|
||||
$jwtAccessToken = $this->accessToken->convertToJWT($this->privateKeyPath);
|
||||
$jwtAccessToken = $this->accessToken->convertToJWT($this->privateKey);
|
||||
|
||||
$responseParams = [
|
||||
'token_type' => 'Bearer',
|
||||
@@ -39,7 +41,7 @@ class BearerTokenResponse extends AbstractResponseType
|
||||
'access_token_id' => $this->accessToken->getIdentifier(),
|
||||
'scopes' => $this->accessToken->getScopes(),
|
||||
'user_id' => $this->accessToken->getUserIdentifier(),
|
||||
'expire_time' => $expireDateTime,
|
||||
'expire_time' => $this->refreshToken->getExpiryDateTime()->getTimestamp(),
|
||||
]
|
||||
)
|
||||
);
|
||||
@@ -47,6 +49,8 @@ class BearerTokenResponse extends AbstractResponseType
|
||||
$responseParams['refresh_token'] = $refreshToken;
|
||||
}
|
||||
|
||||
$responseParams = array_merge($this->getExtraParams($this->accessToken), $responseParams);
|
||||
|
||||
$response = $response
|
||||
->withStatus(200)
|
||||
->withHeader('pragma', 'no-cache')
|
||||
@@ -57,4 +61,18 @@ class BearerTokenResponse extends AbstractResponseType
|
||||
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add custom fields to your Bearer Token response here, then override
|
||||
* AuthorizationServer::getResponseType() to pull in your version of
|
||||
* this class rather than the default.
|
||||
*
|
||||
* @param AccessTokenEntityInterface $accessToken
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function getExtraParams(AccessTokenEntityInterface $accessToken)
|
||||
{
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
@@ -1,66 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace League\OAuth2\Server\ResponseTypes;
|
||||
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
|
||||
class HtmlResponse extends AbstractResponseType
|
||||
{
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $html = '';
|
||||
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
private $statusCode = 200;
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
private $headers = [];
|
||||
|
||||
/**
|
||||
* @param string $html
|
||||
*/
|
||||
public function setHtml($html)
|
||||
{
|
||||
$this->html = $html;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $statusCode
|
||||
*/
|
||||
public function setStatusCode($statusCode = 200)
|
||||
{
|
||||
$this->statusCode = $statusCode;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ResponseInterface $response
|
||||
*
|
||||
* @return ResponseInterface
|
||||
*/
|
||||
public function generateHttpResponse(ResponseInterface $response)
|
||||
{
|
||||
$response->getBody()->write($this->html);
|
||||
|
||||
foreach ($this->headers as $key => $value) {
|
||||
$response = $response->withHeader($key, $value);
|
||||
}
|
||||
|
||||
return $response
|
||||
->withStatus($this->statusCode)
|
||||
->withHeader('content-type', 'text/html');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $key
|
||||
* @param string $value
|
||||
*/
|
||||
public function setHeader($key, $value)
|
||||
{
|
||||
$this->headers[$key] = $value;
|
||||
}
|
||||
}
|
@@ -1,4 +1,13 @@
|
||||
<?php
|
||||
/**
|
||||
* OAuth 2.0 Redirect Response.
|
||||
*
|
||||
* @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\ResponseTypes;
|
||||
|
||||
@@ -26,6 +35,6 @@ class RedirectResponse extends AbstractResponseType
|
||||
*/
|
||||
public function generateHttpResponse(ResponseInterface $response)
|
||||
{
|
||||
return $response->withStatus(302)->withHeader('location', $this->redirectUri);
|
||||
return $response->withStatus(302)->withHeader('Location', $this->redirectUri);
|
||||
}
|
||||
}
|
||||
|
@@ -8,21 +8,22 @@
|
||||
*
|
||||
* @link https://github.com/thephpleague/oauth2-server
|
||||
*/
|
||||
|
||||
namespace League\OAuth2\Server\ResponseTypes;
|
||||
|
||||
use League\OAuth2\Server\Entities\Interfaces\AccessTokenEntityInterface;
|
||||
use League\OAuth2\Server\Entities\Interfaces\RefreshTokenEntityInterface;
|
||||
use League\OAuth2\Server\Entities\AccessTokenEntityInterface;
|
||||
use League\OAuth2\Server\Entities\RefreshTokenEntityInterface;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
|
||||
interface ResponseTypeInterface
|
||||
{
|
||||
/**
|
||||
* @param \League\OAuth2\Server\Entities\Interfaces\AccessTokenEntityInterface $accessToken
|
||||
* @param AccessTokenEntityInterface $accessToken
|
||||
*/
|
||||
public function setAccessToken(AccessTokenEntityInterface $accessToken);
|
||||
|
||||
/**
|
||||
* @param \League\OAuth2\Server\Entities\Interfaces\RefreshTokenEntityInterface $refreshToken
|
||||
* @param RefreshTokenEntityInterface $refreshToken
|
||||
*/
|
||||
public function setRefreshToken(RefreshTokenEntityInterface $refreshToken);
|
||||
|
||||
|
194
src/Server.php
194
src/Server.php
@@ -1,194 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace League\OAuth2\Server;
|
||||
|
||||
use DateInterval;
|
||||
use League\Event\EmitterAwareInterface;
|
||||
use League\Event\EmitterAwareTrait;
|
||||
use League\OAuth2\Server\AuthorizationValidators\AuthorizationValidatorInterface;
|
||||
use League\OAuth2\Server\AuthorizationValidators\BearerTokenValidator;
|
||||
use League\OAuth2\Server\Exception\OAuthServerException;
|
||||
use League\OAuth2\Server\Grant\GrantTypeInterface;
|
||||
use League\OAuth2\Server\Repositories\AccessTokenRepositoryInterface;
|
||||
use League\OAuth2\Server\Repositories\ClientRepositoryInterface;
|
||||
use League\OAuth2\Server\Repositories\ScopeRepositoryInterface;
|
||||
use League\OAuth2\Server\ResponseTypes\BearerTokenResponse;
|
||||
use League\OAuth2\Server\ResponseTypes\ResponseTypeInterface;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
use Psr\Http\Message\ServerRequestInterface;
|
||||
|
||||
class Server implements EmitterAwareInterface
|
||||
{
|
||||
use EmitterAwareTrait;
|
||||
|
||||
/**
|
||||
* @var \League\OAuth2\Server\Grant\GrantTypeInterface[]
|
||||
*/
|
||||
protected $enabledGrantTypes = [];
|
||||
|
||||
/**
|
||||
* @var \DateInterval[]
|
||||
*/
|
||||
protected $grantTypeAccessTokenTTL = [];
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $privateKeyPath;
|
||||
|
||||
/**
|
||||
* @var ResponseTypeInterface
|
||||
*/
|
||||
protected $responseType;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $publicKeyPath;
|
||||
|
||||
/**
|
||||
* @var \League\OAuth2\Server\Repositories\ClientRepositoryInterface
|
||||
*/
|
||||
private $clientRepository;
|
||||
|
||||
/**
|
||||
* @var \League\OAuth2\Server\Repositories\AccessTokenRepositoryInterface
|
||||
*/
|
||||
private $accessTokenRepository;
|
||||
|
||||
/**
|
||||
* @var \League\OAuth2\Server\Repositories\ScopeRepositoryInterface
|
||||
*/
|
||||
private $scopeRepository;
|
||||
|
||||
/**
|
||||
* @var \League\OAuth2\Server\AuthorizationValidators\AuthorizationValidatorInterface
|
||||
*/
|
||||
private $authorizationValidator;
|
||||
|
||||
/**
|
||||
* New server instance.
|
||||
*
|
||||
* @param \League\OAuth2\Server\Repositories\ClientRepositoryInterface $clientRepository
|
||||
* @param \League\OAuth2\Server\Repositories\AccessTokenRepositoryInterface $accessTokenRepository
|
||||
* @param \League\OAuth2\Server\Repositories\ScopeRepositoryInterface $scopeRepository
|
||||
* @param string $privateKeyPath
|
||||
* @param string $publicKeyPath
|
||||
* @param null|\League\OAuth2\Server\ResponseTypes\ResponseTypeInterface $responseType
|
||||
* @param null|\League\OAuth2\Server\AuthorizationValidators\AuthorizationValidatorInterface $authorizationValidator
|
||||
*/
|
||||
public function __construct(
|
||||
ClientRepositoryInterface $clientRepository,
|
||||
AccessTokenRepositoryInterface $accessTokenRepository,
|
||||
ScopeRepositoryInterface $scopeRepository,
|
||||
$privateKeyPath,
|
||||
$publicKeyPath,
|
||||
ResponseTypeInterface $responseType = null,
|
||||
AuthorizationValidatorInterface $authorizationValidator = null
|
||||
) {
|
||||
$this->clientRepository = $clientRepository;
|
||||
$this->accessTokenRepository = $accessTokenRepository;
|
||||
$this->scopeRepository = $scopeRepository;
|
||||
$this->privateKeyPath = $privateKeyPath;
|
||||
$this->publicKeyPath = $publicKeyPath;
|
||||
$this->responseType = $responseType;
|
||||
$this->authorizationValidator = $authorizationValidator;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable a grant type on the server.
|
||||
*
|
||||
* @param \League\OAuth2\Server\Grant\GrantTypeInterface $grantType
|
||||
* @param \DateInterval $accessTokenTTL
|
||||
*/
|
||||
public function enableGrantType(GrantTypeInterface $grantType, DateInterval $accessTokenTTL)
|
||||
{
|
||||
$grantType->setAccessTokenRepository($this->accessTokenRepository);
|
||||
$grantType->setClientRepository($this->clientRepository);
|
||||
$grantType->setScopeRepository($this->scopeRepository);
|
||||
$grantType->setPrivateKeyPath($this->privateKeyPath);
|
||||
$grantType->setPublicKeyPath($this->publicKeyPath);
|
||||
$grantType->setEmitter($this->getEmitter());
|
||||
|
||||
$this->enabledGrantTypes[$grantType->getIdentifier()] = $grantType;
|
||||
|
||||
$this->grantTypeAccessTokenTTL[$grantType->getIdentifier()] = $accessTokenTTL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return an access token response.
|
||||
*
|
||||
* @param \Psr\Http\Message\ServerRequestInterface|null $request
|
||||
* @param \Psr\Http\Message\ResponseInterface|null $response
|
||||
*
|
||||
* @throws \League\OAuth2\Server\Exception\OAuthServerException
|
||||
*
|
||||
* @return \Psr\Http\Message\ResponseInterface
|
||||
*/
|
||||
public function respondToRequest(ServerRequestInterface $request, ResponseInterface $response)
|
||||
{
|
||||
$tokenResponse = null;
|
||||
while ($tokenResponse === null && $grantType = array_shift($this->enabledGrantTypes)) {
|
||||
/** @var \League\OAuth2\Server\Grant\GrantTypeInterface $grantType */
|
||||
if ($grantType->canRespondToRequest($request)) {
|
||||
$tokenResponse = $grantType->respondToRequest(
|
||||
$request,
|
||||
$this->getResponseType(),
|
||||
$this->grantTypeAccessTokenTTL[$grantType->getIdentifier()]
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if ($tokenResponse instanceof ResponseTypeInterface) {
|
||||
return $tokenResponse->generateHttpResponse($response);
|
||||
}
|
||||
|
||||
throw OAuthServerException::unsupportedGrantType();
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine the access token validity.
|
||||
*
|
||||
* @param \Psr\Http\Message\ServerRequestInterface $request
|
||||
*
|
||||
* @throws \League\OAuth2\Server\Exception\OAuthServerException
|
||||
*
|
||||
* @return \Psr\Http\Message\ServerRequestInterface
|
||||
*/
|
||||
public function validateAuthenticatedRequest(ServerRequestInterface $request)
|
||||
{
|
||||
return $this->getAuthorizationValidator()->validateAuthorization($request);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the token type that grants will return in the HTTP response.
|
||||
*
|
||||
* @return ResponseTypeInterface
|
||||
*/
|
||||
protected function getResponseType()
|
||||
{
|
||||
if (!$this->responseType instanceof ResponseTypeInterface) {
|
||||
$this->responseType = new BearerTokenResponse($this->accessTokenRepository);
|
||||
}
|
||||
|
||||
$this->responseType->setPublicKeyPath($this->publicKeyPath);
|
||||
$this->responseType->setPrivateKeyPath($this->privateKeyPath);
|
||||
|
||||
return $this->responseType;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \League\OAuth2\Server\AuthorizationValidators\AuthorizationValidatorInterface
|
||||
*/
|
||||
protected function getAuthorizationValidator()
|
||||
{
|
||||
if (!$this->authorizationValidator instanceof AuthorizationValidatorInterface) {
|
||||
$this->authorizationValidator = new BearerTokenValidator($this->accessTokenRepository);
|
||||
}
|
||||
|
||||
$this->authorizationValidator->setPublicKeyPath($this->publicKeyPath);
|
||||
$this->authorizationValidator->setPrivateKeyPath($this->privateKeyPath);
|
||||
|
||||
return $this->authorizationValidator;
|
||||
}
|
||||
}
|
@@ -1,70 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Base template renderer.
|
||||
*
|
||||
* @author Julián Gutiérrez <juliangut@gmail.com>
|
||||
* @copyright Copyright (c) Alex Bilbie
|
||||
* @license http://mit-license.org/
|
||||
*
|
||||
* @link https://github.com/thephpleague/oauth2-server
|
||||
*/
|
||||
namespace League\OAuth2\Server\TemplateRenderer;
|
||||
|
||||
abstract class AbstractRenderer implements RendererInterface
|
||||
{
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $loginTemplate;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $authorizeTemplate;
|
||||
|
||||
/**
|
||||
* PlatesRenderer constructor.
|
||||
*
|
||||
* @param string $loginTemplate
|
||||
* @param string $authorizeTemplate
|
||||
*/
|
||||
public function __construct($loginTemplate, $authorizeTemplate)
|
||||
{
|
||||
$this->loginTemplate = $loginTemplate;
|
||||
$this->authorizeTemplate = $authorizeTemplate;
|
||||
}
|
||||
|
||||
/**
|
||||
* Render login template.
|
||||
*
|
||||
* @param array $data
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function renderLogin(array $data = [])
|
||||
{
|
||||
return $this->render($this->loginTemplate, $data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Render authorize template.
|
||||
*
|
||||
* @param array $data
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function renderAuthorize(array $data = [])
|
||||
{
|
||||
return $this->render($this->authorizeTemplate, $data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Render template.
|
||||
*
|
||||
* @param string $template
|
||||
* @param array $data
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
abstract protected function render($template, array $data = []);
|
||||
}
|
@@ -1,35 +0,0 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Authorize <?=$this->e($client->getName())?></title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<h1>
|
||||
Authorize <?=$this->e($client->getName())?>
|
||||
</h1>
|
||||
|
||||
<p>
|
||||
Do you want to authorize <?=$this->e($client->getName())?> to access the following data?
|
||||
</p>
|
||||
|
||||
<ul>
|
||||
<?php foreach ($scopes as $scope): ?>
|
||||
<li><?=$scope->getIdentifier()?></li>
|
||||
<?php endforeach; ?>
|
||||
</ul>
|
||||
|
||||
<form method="POST">
|
||||
<input type="hidden" value="approve" name="action">
|
||||
<button type="submit">Approve</button>
|
||||
</form>
|
||||
|
||||
<form method="POST">
|
||||
<input type="hidden" value="deny" name="action">
|
||||
<button type="submit">Deny</button>
|
||||
</form>
|
||||
|
||||
</body>
|
||||
</html>
|
@@ -1,35 +0,0 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Login</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<h1>Login</h1>
|
||||
|
||||
<?php if ($error !== null): ?>
|
||||
<div style="border:solid 1px red; padding: 1rem; margin-bottom:1rem">
|
||||
<?=$this->e($error)?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<form method="POST">
|
||||
|
||||
<label for="username">Username</label>
|
||||
<input type="text" id="username" name="username">
|
||||
|
||||
<br>
|
||||
|
||||
<label for="password">Password</label>
|
||||
<input type="password" id="password" name="password">
|
||||
|
||||
<br>
|
||||
|
||||
<input type="submit" value="Login">
|
||||
|
||||
</form>
|
||||
|
||||
</body>
|
||||
</html>
|
@@ -1,41 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Mustache template renderer bridge.
|
||||
*
|
||||
* @author Julián Gutiérrez <juliangut@gmail.com>
|
||||
* @copyright Copyright (c) Alex Bilbie
|
||||
* @license http://mit-license.org/
|
||||
*
|
||||
* @link https://github.com/thephpleague/oauth2-server
|
||||
*/
|
||||
namespace League\OAuth2\Server\TemplateRenderer;
|
||||
|
||||
class MustacheRenderer extends AbstractRenderer
|
||||
{
|
||||
/**
|
||||
* @var \Mustache_Engine
|
||||
*/
|
||||
private $engine;
|
||||
|
||||
/**
|
||||
* PlatesRenderer constructor.
|
||||
*
|
||||
* @param \Mustache_Engine $engine
|
||||
* @param string $loginTemplate
|
||||
* @param string $authorizeTemplate
|
||||
*/
|
||||
public function __construct(\Mustache_Engine $engine, $loginTemplate, $authorizeTemplate)
|
||||
{
|
||||
parent::__construct($loginTemplate, $authorizeTemplate);
|
||||
|
||||
$this->engine = $engine;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function render($template, array $data = [])
|
||||
{
|
||||
return $this->engine->render($template, $data);
|
||||
}
|
||||
}
|
@@ -1,47 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Plates template renderer bridge.
|
||||
*
|
||||
* @author Julián Gutiérrez <juliangut@gmail.com>
|
||||
* @copyright Copyright (c) Alex Bilbie
|
||||
* @license http://mit-license.org/
|
||||
*
|
||||
* @link https://github.com/thephpleague/oauth2-server
|
||||
*/
|
||||
namespace League\OAuth2\Server\TemplateRenderer;
|
||||
|
||||
use League\Plates\Engine;
|
||||
|
||||
class PlatesRenderer extends AbstractRenderer
|
||||
{
|
||||
/**
|
||||
* @var \League\Plates\Engine
|
||||
*/
|
||||
private $engine;
|
||||
|
||||
/**
|
||||
* PlatesRenderer constructor.
|
||||
*
|
||||
* @param \League\Plates\Engine $engine
|
||||
* @param string $loginTemplate
|
||||
* @param string $authorizeTemplate
|
||||
*/
|
||||
public function __construct(Engine $engine, $loginTemplate, $authorizeTemplate)
|
||||
{
|
||||
parent::__construct($loginTemplate, $authorizeTemplate);
|
||||
|
||||
$this->engine = $engine;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function render($template, array $data = [])
|
||||
{
|
||||
if ($this->engine->getFileExtension()) {
|
||||
$template = preg_replace(sprintf('/\.%s$/', $this->engine->getFileExtension()), '', $template);
|
||||
}
|
||||
|
||||
return $this->engine->render($template, $data);
|
||||
}
|
||||
}
|
@@ -1,24 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace League\OAuth2\Server\TemplateRenderer;
|
||||
|
||||
interface RendererInterface
|
||||
{
|
||||
/**
|
||||
* Render login template.
|
||||
*
|
||||
* @param array $data
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function renderLogin(array $data = []);
|
||||
|
||||
/**
|
||||
* Render authorize template.
|
||||
*
|
||||
* @param array $data
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function renderAuthorize(array $data = []);
|
||||
}
|
@@ -1,49 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Smarty template renderer bridge.
|
||||
*
|
||||
* @author Julián Gutiérrez <juliangut@gmail.com>
|
||||
* @copyright Copyright (c) Alex Bilbie
|
||||
* @license http://mit-license.org/
|
||||
*
|
||||
* @link https://github.com/thephpleague/oauth2-server
|
||||
*/
|
||||
namespace League\OAuth2\Server\TemplateRenderer;
|
||||
|
||||
class SmartyRenderer extends AbstractRenderer
|
||||
{
|
||||
/**
|
||||
* Smarty class.
|
||||
*
|
||||
* @var \Smarty
|
||||
*/
|
||||
private $smarty;
|
||||
|
||||
/**
|
||||
* PlatesRenderer constructor.
|
||||
*
|
||||
* @param \Smarty $smarty
|
||||
* @param string $loginTemplate
|
||||
* @param string $authorizeTemplate
|
||||
*/
|
||||
public function __construct(\Smarty $smarty, $loginTemplate, $authorizeTemplate)
|
||||
{
|
||||
parent::__construct($loginTemplate, $authorizeTemplate);
|
||||
|
||||
$this->smarty = $smarty;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function render($template, array $data = [])
|
||||
{
|
||||
$this->smarty->assign($data);
|
||||
|
||||
$output = $this->smarty->fetch($template);
|
||||
|
||||
$this->smarty->clear_assign(array_keys($data));
|
||||
|
||||
return $output;
|
||||
}
|
||||
}
|
@@ -1,41 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Twig template renderer bridge.
|
||||
*
|
||||
* @author Julián Gutiérrez <juliangut@gmail.com>
|
||||
* @copyright Copyright (c) Alex Bilbie
|
||||
* @license http://mit-license.org/
|
||||
*
|
||||
* @link https://github.com/thephpleague/oauth2-server
|
||||
*/
|
||||
namespace League\OAuth2\Server\TemplateRenderer;
|
||||
|
||||
class TwigRenderer extends AbstractRenderer
|
||||
{
|
||||
/**
|
||||
* @var \Twig_Environment
|
||||
*/
|
||||
private $environment;
|
||||
|
||||
/**
|
||||
* PlatesRenderer constructor.
|
||||
*
|
||||
* @param \Twig_Environment $environment
|
||||
* @param string $loginTemplate
|
||||
* @param string $authorizeTemplate
|
||||
*/
|
||||
public function __construct(\Twig_Environment $environment, $loginTemplate, $authorizeTemplate)
|
||||
{
|
||||
parent::__construct($loginTemplate, $authorizeTemplate);
|
||||
|
||||
$this->environment = $environment;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function render($template, array $data = [])
|
||||
{
|
||||
return $this->environment->loadTemplate($template)->render($data);
|
||||
}
|
||||
}
|
204
tests/AuthorizationServerTest.php
Normal file
204
tests/AuthorizationServerTest.php
Normal file
@@ -0,0 +1,204 @@
|
||||
<?php
|
||||
|
||||
namespace LeagueTests;
|
||||
|
||||
use League\OAuth2\Server\AuthorizationServer;
|
||||
use League\OAuth2\Server\CryptKey;
|
||||
use League\OAuth2\Server\Exception\OAuthServerException;
|
||||
use League\OAuth2\Server\Grant\AuthCodeGrant;
|
||||
use League\OAuth2\Server\Grant\ClientCredentialsGrant;
|
||||
use League\OAuth2\Server\Repositories\AccessTokenRepositoryInterface;
|
||||
use League\OAuth2\Server\Repositories\AuthCodeRepositoryInterface;
|
||||
use League\OAuth2\Server\Repositories\ClientRepositoryInterface;
|
||||
use League\OAuth2\Server\Repositories\RefreshTokenRepositoryInterface;
|
||||
use League\OAuth2\Server\Repositories\ScopeRepositoryInterface;
|
||||
use League\OAuth2\Server\RequestTypes\AuthorizationRequest;
|
||||
use League\OAuth2\Server\ResponseTypes\BearerTokenResponse;
|
||||
use LeagueTests\Stubs\AccessTokenEntity;
|
||||
use LeagueTests\Stubs\AuthCodeEntity;
|
||||
use LeagueTests\Stubs\ClientEntity;
|
||||
use LeagueTests\Stubs\StubResponseType;
|
||||
use LeagueTests\Stubs\UserEntity;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
use Zend\Diactoros\Response;
|
||||
use Zend\Diactoros\ServerRequest;
|
||||
use Zend\Diactoros\ServerRequestFactory;
|
||||
|
||||
class AuthorizationServerTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
public function testRespondToRequestInvalidGrantType()
|
||||
{
|
||||
$server = new AuthorizationServer(
|
||||
$this->getMockBuilder(ClientRepositoryInterface::class)->getMock(),
|
||||
$this->getMockBuilder(AccessTokenRepositoryInterface::class)->getMock(),
|
||||
$this->getMockBuilder(ScopeRepositoryInterface::class)->getMock(),
|
||||
'file://' . __DIR__ . '/Stubs/private.key',
|
||||
'file://' . __DIR__ . '/Stubs/public.key',
|
||||
new StubResponseType()
|
||||
);
|
||||
|
||||
$server->enableGrantType(new ClientCredentialsGrant(), new \DateInterval('PT1M'));
|
||||
|
||||
try {
|
||||
$server->respondToAccessTokenRequest(ServerRequestFactory::fromGlobals(), new Response);
|
||||
} catch (OAuthServerException $e) {
|
||||
$this->assertEquals('unsupported_grant_type', $e->getErrorType());
|
||||
$this->assertEquals(400, $e->getHttpStatusCode());
|
||||
}
|
||||
}
|
||||
|
||||
public function testRespondToRequest()
|
||||
{
|
||||
$clientRepository = $this->getMockBuilder(ClientRepositoryInterface::class)->getMock();
|
||||
$clientRepository->method('getClientEntity')->willReturn(new ClientEntity());
|
||||
|
||||
$scopeRepositoryMock = $this->getMockBuilder(ScopeRepositoryInterface::class)->getMock();
|
||||
$scopeRepositoryMock->method('finalizeScopes')->willReturnArgument(0);
|
||||
|
||||
$accessTokenRepositoryMock = $this->getMockBuilder(AccessTokenRepositoryInterface::class)->getMock();
|
||||
$accessTokenRepositoryMock->method('getNewToken')->willReturn(new AccessTokenEntity());
|
||||
|
||||
$server = new AuthorizationServer(
|
||||
$clientRepository,
|
||||
$accessTokenRepositoryMock,
|
||||
$scopeRepositoryMock,
|
||||
'file://' . __DIR__ . '/Stubs/private.key',
|
||||
'file://' . __DIR__ . '/Stubs/public.key',
|
||||
new StubResponseType()
|
||||
);
|
||||
|
||||
$server->enableGrantType(new ClientCredentialsGrant(), new \DateInterval('PT1M'));
|
||||
|
||||
$_POST['grant_type'] = 'client_credentials';
|
||||
$_POST['client_id'] = 'foo';
|
||||
$_POST['client_secret'] = 'bar';
|
||||
$response = $server->respondToAccessTokenRequest(ServerRequestFactory::fromGlobals(), new Response);
|
||||
$this->assertEquals(200, $response->getStatusCode());
|
||||
}
|
||||
|
||||
public function testGetResponseType()
|
||||
{
|
||||
$clientRepository = $this->getMockBuilder(ClientRepositoryInterface::class)->getMock();
|
||||
|
||||
$server = new AuthorizationServer(
|
||||
$clientRepository,
|
||||
$this->getMockBuilder(AccessTokenRepositoryInterface::class)->getMock(),
|
||||
$this->getMockBuilder(ScopeRepositoryInterface::class)->getMock(),
|
||||
'file://' . __DIR__ . '/Stubs/private.key',
|
||||
'file://' . __DIR__ . '/Stubs/public.key'
|
||||
);
|
||||
|
||||
$abstractGrantReflection = new \ReflectionClass($server);
|
||||
$method = $abstractGrantReflection->getMethod('getResponseType');
|
||||
$method->setAccessible(true);
|
||||
|
||||
$this->assertTrue($method->invoke($server) instanceof BearerTokenResponse);
|
||||
}
|
||||
|
||||
public function testCompleteAuthorizationRequest()
|
||||
{
|
||||
$clientRepository = $this->getMockBuilder(ClientRepositoryInterface::class)->getMock();
|
||||
|
||||
$server = new AuthorizationServer(
|
||||
$clientRepository,
|
||||
$this->getMockBuilder(AccessTokenRepositoryInterface::class)->getMock(),
|
||||
$this->getMockBuilder(ScopeRepositoryInterface::class)->getMock(),
|
||||
'file://' . __DIR__ . '/Stubs/private.key',
|
||||
'file://' . __DIR__ . '/Stubs/public.key'
|
||||
);
|
||||
|
||||
$authCodeRepository = $this->getMockBuilder(AuthCodeRepositoryInterface::class)->getMock();
|
||||
$authCodeRepository->method('getNewAuthCode')->willReturn(new AuthCodeEntity());
|
||||
|
||||
$grant = new AuthCodeGrant(
|
||||
$authCodeRepository,
|
||||
$this->getMockBuilder(RefreshTokenRepositoryInterface::class)->getMock(),
|
||||
new \DateInterval('PT10M')
|
||||
);
|
||||
|
||||
$grant->setPrivateKey(new CryptKey('file://' . __DIR__ . '/Stubs/private.key'));
|
||||
$grant->setPublicKey(new CryptKey('file://' . __DIR__ . '/Stubs/public.key'));
|
||||
|
||||
$server->enableGrantType($grant);
|
||||
|
||||
$authRequest = new AuthorizationRequest();
|
||||
$authRequest->setAuthorizationApproved(true);
|
||||
$authRequest->setClient(new ClientEntity());
|
||||
$authRequest->setGrantTypeId('authorization_code');
|
||||
$authRequest->setUser(new UserEntity());
|
||||
|
||||
$this->assertTrue(
|
||||
$server->completeAuthorizationRequest($authRequest, new Response) instanceof ResponseInterface
|
||||
);
|
||||
}
|
||||
|
||||
public function testValidateAuthorizationRequest()
|
||||
{
|
||||
$client = new ClientEntity();
|
||||
$clientRepositoryMock = $this->getMockBuilder(ClientRepositoryInterface::class)->getMock();
|
||||
$clientRepositoryMock->method('getClientEntity')->willReturn($client);
|
||||
|
||||
$grant = new AuthCodeGrant(
|
||||
$this->getMockBuilder(AuthCodeRepositoryInterface::class)->getMock(),
|
||||
$this->getMockBuilder(RefreshTokenRepositoryInterface::class)->getMock(),
|
||||
new \DateInterval('PT10M')
|
||||
);
|
||||
$grant->setClientRepository($clientRepositoryMock);
|
||||
|
||||
$server = new AuthorizationServer(
|
||||
$clientRepositoryMock,
|
||||
$this->getMockBuilder(AccessTokenRepositoryInterface::class)->getMock(),
|
||||
$this->getMockBuilder(ScopeRepositoryInterface::class)->getMock(),
|
||||
'file://' . __DIR__ . '/Stubs/private.key',
|
||||
'file://' . __DIR__ . '/Stubs/public.key'
|
||||
);
|
||||
$server->enableGrantType($grant);
|
||||
|
||||
$request = new ServerRequest(
|
||||
[],
|
||||
[],
|
||||
null,
|
||||
null,
|
||||
'php://input',
|
||||
$headers = [],
|
||||
$cookies = [],
|
||||
$queryParams = [
|
||||
'response_type' => 'code',
|
||||
'client_id' => 'foo',
|
||||
]
|
||||
);
|
||||
|
||||
$this->assertTrue($server->validateAuthorizationRequest($request) instanceof AuthorizationRequest);
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \League\OAuth2\Server\Exception\OAuthServerException
|
||||
* @expectedExceptionCode 2
|
||||
*/
|
||||
public function testValidateAuthorizationRequestUnregistered()
|
||||
{
|
||||
$server = new AuthorizationServer(
|
||||
$this->getMockBuilder(ClientRepositoryInterface::class)->getMock(),
|
||||
$this->getMockBuilder(AccessTokenRepositoryInterface::class)->getMock(),
|
||||
$this->getMockBuilder(ScopeRepositoryInterface::class)->getMock(),
|
||||
'file://' . __DIR__ . '/Stubs/private.key',
|
||||
'file://' . __DIR__ . '/Stubs/public.key'
|
||||
);
|
||||
|
||||
$request = new ServerRequest(
|
||||
[],
|
||||
[],
|
||||
null,
|
||||
null,
|
||||
'php://input',
|
||||
$headers = [],
|
||||
$cookies = [],
|
||||
$queryParams = [
|
||||
'response_type' => 'code',
|
||||
'client_id' => 'foo',
|
||||
]
|
||||
);
|
||||
|
||||
$server->validateAuthorizationRequest($request);
|
||||
}
|
||||
}
|
36
tests/CryptKeyTest.php
Normal file
36
tests/CryptKeyTest.php
Normal file
@@ -0,0 +1,36 @@
|
||||
<?php
|
||||
|
||||
namespace LeagueTests\Utils;
|
||||
|
||||
use League\OAuth2\Server\CryptKey;
|
||||
|
||||
class CryptKeyTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
/**
|
||||
* @expectedException \LogicException
|
||||
*/
|
||||
public function testNoFile()
|
||||
{
|
||||
new CryptKey('undefined file');
|
||||
}
|
||||
|
||||
public function testKeyCreation()
|
||||
{
|
||||
$keyFile = __DIR__ . '/Stubs/public.key';
|
||||
$key = new CryptKey($keyFile, 'secret');
|
||||
|
||||
$this->assertEquals('file://' . $keyFile, $key->getKeyPath());
|
||||
$this->assertEquals('secret', $key->getPassPhrase());
|
||||
}
|
||||
|
||||
public function testKeyFileCreation()
|
||||
{
|
||||
$keyContent = file_get_contents(__DIR__ . '/Stubs/public.key');
|
||||
$key = new CryptKey($keyContent);
|
||||
|
||||
$this->assertEquals(
|
||||
'file://' . sys_get_temp_dir() . '/' . sha1($keyContent) . '.key',
|
||||
$key->getKeyPath()
|
||||
);
|
||||
}
|
||||
}
|
@@ -2,6 +2,7 @@
|
||||
|
||||
namespace LeagueTests\Utils;
|
||||
|
||||
use League\OAuth2\Server\CryptKey;
|
||||
use LeagueTests\Stubs\CryptTraitStub;
|
||||
|
||||
class CryptTraitTest extends \PHPUnit_Framework_TestCase
|
||||
@@ -31,7 +32,7 @@ class CryptTraitTest extends \PHPUnit_Framework_TestCase
|
||||
*/
|
||||
public function testBadPrivateKey()
|
||||
{
|
||||
$this->cryptStub->setPrivateKeyPath(__DIR__ . '/Stubs/public.key');
|
||||
$this->cryptStub->setPrivateKey(new CryptKey(__DIR__ . '/Stubs/public.key'));
|
||||
$this->cryptStub->doEncrypt('');
|
||||
}
|
||||
|
||||
@@ -40,7 +41,15 @@ class CryptTraitTest extends \PHPUnit_Framework_TestCase
|
||||
*/
|
||||
public function testBadPublicKey()
|
||||
{
|
||||
$this->cryptStub->setPublicKeyPath(__DIR__ . '/Stubs/private.key');
|
||||
$this->cryptStub->setPublicKey(new CryptKey(__DIR__ . '/Stubs/private.key'));
|
||||
$this->cryptStub->doDecrypt('');
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \LogicException
|
||||
*/
|
||||
public function testNonExistentKey()
|
||||
{
|
||||
new CryptKey('foo/bar');
|
||||
}
|
||||
}
|
||||
|
@@ -3,17 +3,21 @@
|
||||
namespace LeagueTests\Grant;
|
||||
|
||||
use League\Event\Emitter;
|
||||
use League\OAuth2\Server\Entities\AccessTokenEntity;
|
||||
use League\OAuth2\Server\Entities\Interfaces\AccessTokenEntityInterface;
|
||||
use League\OAuth2\Server\Entities\Interfaces\AuthCodeEntityInterface;
|
||||
use League\OAuth2\Server\Entities\Interfaces\RefreshTokenEntityInterface;
|
||||
use League\OAuth2\Server\CryptKey;
|
||||
use League\OAuth2\Server\Entities\AccessTokenEntityInterface;
|
||||
use League\OAuth2\Server\Entities\AuthCodeEntityInterface;
|
||||
use League\OAuth2\Server\Entities\RefreshTokenEntityInterface;
|
||||
use League\OAuth2\Server\Grant\AbstractGrant;
|
||||
use League\OAuth2\Server\Repositories\AccessTokenRepositoryInterface;
|
||||
use League\OAuth2\Server\Repositories\AuthCodeRepositoryInterface;
|
||||
use League\OAuth2\Server\Repositories\ClientRepositoryInterface;
|
||||
use League\OAuth2\Server\Repositories\RefreshTokenRepositoryInterface;
|
||||
use League\OAuth2\Server\Repositories\ScopeRepositoryInterface;
|
||||
use League\OAuth2\Server\RequestTypes\AuthorizationRequest;
|
||||
use LeagueTests\Stubs\AccessTokenEntity;
|
||||
use LeagueTests\Stubs\AuthCodeEntity;
|
||||
use LeagueTests\Stubs\ClientEntity;
|
||||
use LeagueTests\Stubs\RefreshTokenEntity;
|
||||
use LeagueTests\Stubs\ScopeEntity;
|
||||
use Zend\Diactoros\ServerRequest;
|
||||
|
||||
@@ -23,11 +27,81 @@ class AbstractGrantTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
/** @var AbstractGrant $grantMock */
|
||||
$grantMock = $this->getMockForAbstractClass(AbstractGrant::class);
|
||||
$grantMock->setPrivateKeyPath('./private.key');
|
||||
$grantMock->setPublicKeyPath('./public.key');
|
||||
$grantMock->setPrivateKey(new CryptKey(__DIR__ . '/../Stubs/private.key'));
|
||||
$grantMock->setPublicKey(new CryptKey(__DIR__ . '/../Stubs/public.key'));
|
||||
$grantMock->setEmitter(new Emitter());
|
||||
}
|
||||
|
||||
public function testHttpBasicWithPassword()
|
||||
{
|
||||
/** @var AbstractGrant $grantMock */
|
||||
$grantMock = $this->getMockForAbstractClass(AbstractGrant::class);
|
||||
$abstractGrantReflection = new \ReflectionClass($grantMock);
|
||||
|
||||
$serverRequest = new ServerRequest();
|
||||
$serverRequest = $serverRequest->withHeader('Authorization', 'Basic ' . base64_encode('Open:Sesame'));
|
||||
$basicAuthMethod = $abstractGrantReflection->getMethod('getBasicAuthCredentials');
|
||||
$basicAuthMethod->setAccessible(true);
|
||||
|
||||
$this->assertSame(['Open', 'Sesame'], $basicAuthMethod->invoke($grantMock, $serverRequest));
|
||||
}
|
||||
|
||||
public function testHttpBasicNoPassword()
|
||||
{
|
||||
/** @var AbstractGrant $grantMock */
|
||||
$grantMock = $this->getMockForAbstractClass(AbstractGrant::class);
|
||||
$abstractGrantReflection = new \ReflectionClass($grantMock);
|
||||
|
||||
$serverRequest = new ServerRequest();
|
||||
$serverRequest = $serverRequest->withHeader('Authorization', 'Basic ' . base64_encode('Open:'));
|
||||
$basicAuthMethod = $abstractGrantReflection->getMethod('getBasicAuthCredentials');
|
||||
$basicAuthMethod->setAccessible(true);
|
||||
|
||||
$this->assertSame(['Open', ''], $basicAuthMethod->invoke($grantMock, $serverRequest));
|
||||
}
|
||||
|
||||
public function testHttpBasicNotBasic()
|
||||
{
|
||||
/** @var AbstractGrant $grantMock */
|
||||
$grantMock = $this->getMockForAbstractClass(AbstractGrant::class);
|
||||
$abstractGrantReflection = new \ReflectionClass($grantMock);
|
||||
|
||||
$serverRequest = new ServerRequest();
|
||||
$serverRequest = $serverRequest->withHeader('Authorization', 'Foo ' . base64_encode('Open:Sesame'));
|
||||
$basicAuthMethod = $abstractGrantReflection->getMethod('getBasicAuthCredentials');
|
||||
$basicAuthMethod->setAccessible(true);
|
||||
|
||||
$this->assertSame([null, null], $basicAuthMethod->invoke($grantMock, $serverRequest));
|
||||
}
|
||||
|
||||
public function testHttpBasicNotBase64()
|
||||
{
|
||||
/** @var AbstractGrant $grantMock */
|
||||
$grantMock = $this->getMockForAbstractClass(AbstractGrant::class);
|
||||
$abstractGrantReflection = new \ReflectionClass($grantMock);
|
||||
|
||||
$serverRequest = new ServerRequest();
|
||||
$serverRequest = $serverRequest->withHeader('Authorization', 'Basic ||');
|
||||
$basicAuthMethod = $abstractGrantReflection->getMethod('getBasicAuthCredentials');
|
||||
$basicAuthMethod->setAccessible(true);
|
||||
|
||||
$this->assertSame([null, null], $basicAuthMethod->invoke($grantMock, $serverRequest));
|
||||
}
|
||||
|
||||
public function testHttpBasicNoColon()
|
||||
{
|
||||
/** @var AbstractGrant $grantMock */
|
||||
$grantMock = $this->getMockForAbstractClass(AbstractGrant::class);
|
||||
$abstractGrantReflection = new \ReflectionClass($grantMock);
|
||||
|
||||
$serverRequest = new ServerRequest();
|
||||
$serverRequest = $serverRequest->withHeader('Authorization', 'Basic ' . base64_encode('OpenSesame'));
|
||||
$basicAuthMethod = $abstractGrantReflection->getMethod('getBasicAuthCredentials');
|
||||
$basicAuthMethod->setAccessible(true);
|
||||
|
||||
$this->assertSame([null, null], $basicAuthMethod->invoke($grantMock, $serverRequest));
|
||||
}
|
||||
|
||||
public function testValidateClientPublic()
|
||||
{
|
||||
$client = new ClientEntity();
|
||||
@@ -57,8 +131,6 @@ class AbstractGrantTest extends \PHPUnit_Framework_TestCase
|
||||
public function testValidateClientConfidential()
|
||||
{
|
||||
$client = new ClientEntity();
|
||||
$client->setSecret('bar');
|
||||
$client->setRedirectUri('http://foo/bar');
|
||||
|
||||
$clientRepositoryMock = $this->getMockBuilder(ClientRepositoryInterface::class)->getMock();
|
||||
$clientRepositoryMock->method('getClientEntity')->willReturn($client);
|
||||
@@ -175,8 +247,36 @@ class AbstractGrantTest extends \PHPUnit_Framework_TestCase
|
||||
|
||||
$serverRequest = new ServerRequest();
|
||||
$serverRequest = $serverRequest->withParsedBody([
|
||||
'client_id' => 'foo',
|
||||
'redirect_uri' => 'http://bar/foo',
|
||||
'client_id' => 'foo',
|
||||
'redirect_uri' => 'http://bar/foo',
|
||||
]);
|
||||
|
||||
$validateClientMethod = $abstractGrantReflection->getMethod('validateClient');
|
||||
$validateClientMethod->setAccessible(true);
|
||||
|
||||
$validateClientMethod->invoke($grantMock, $serverRequest, true, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \League\OAuth2\Server\Exception\OAuthServerException
|
||||
*/
|
||||
public function testValidateClientInvalidRedirectUriArray()
|
||||
{
|
||||
$client = new ClientEntity();
|
||||
$client->setRedirectUri(['http://foo/bar']);
|
||||
$clientRepositoryMock = $this->getMockBuilder(ClientRepositoryInterface::class)->getMock();
|
||||
$clientRepositoryMock->method('getClientEntity')->willReturn($client);
|
||||
|
||||
/** @var AbstractGrant $grantMock */
|
||||
$grantMock = $this->getMockForAbstractClass(AbstractGrant::class);
|
||||
$grantMock->setClientRepository($clientRepositoryMock);
|
||||
|
||||
$abstractGrantReflection = new \ReflectionClass($grantMock);
|
||||
|
||||
$serverRequest = new ServerRequest();
|
||||
$serverRequest = $serverRequest->withParsedBody([
|
||||
'client_id' => 'foo',
|
||||
'redirect_uri' => 'http://bar/foo',
|
||||
]);
|
||||
|
||||
$validateClientMethod = $abstractGrantReflection->getMethod('validateClient');
|
||||
@@ -221,12 +321,16 @@ class AbstractGrantTest extends \PHPUnit_Framework_TestCase
|
||||
'grant_type' => 'foobar',
|
||||
]);
|
||||
|
||||
$this->assertTrue($grantMock->canRespondToRequest($serverRequest));
|
||||
$this->assertTrue($grantMock->canRespondToAccessTokenRequest($serverRequest));
|
||||
}
|
||||
|
||||
public function testIssueRefreshToken()
|
||||
{
|
||||
$refreshTokenRepoMock = $this->getMock(RefreshTokenRepositoryInterface::class);
|
||||
$refreshTokenRepoMock = $this->getMockBuilder(RefreshTokenRepositoryInterface::class)->getMock();
|
||||
$refreshTokenRepoMock
|
||||
->expects($this->once())
|
||||
->method('getNewRefreshToken')
|
||||
->willReturn(new RefreshTokenEntity());
|
||||
|
||||
/** @var AbstractGrant $grantMock */
|
||||
$grantMock = $this->getMockForAbstractClass(AbstractGrant::class);
|
||||
@@ -241,13 +345,13 @@ class AbstractGrantTest extends \PHPUnit_Framework_TestCase
|
||||
/** @var RefreshTokenEntityInterface $refreshToken */
|
||||
$refreshToken = $issueRefreshTokenMethod->invoke($grantMock, $accessToken);
|
||||
$this->assertTrue($refreshToken instanceof RefreshTokenEntityInterface);
|
||||
$this->assertFalse($refreshToken->isExpired());
|
||||
$this->assertEquals($accessToken, $refreshToken->getAccessToken());
|
||||
}
|
||||
|
||||
public function testIssueAccessToken()
|
||||
{
|
||||
$accessTokenRepoMock = $this->getMock(AccessTokenRepositoryInterface::class);
|
||||
$accessTokenRepoMock = $this->getMockBuilder(AccessTokenRepositoryInterface::class)->getMock();
|
||||
$accessTokenRepoMock->method('getNewToken')->willReturn(new AccessTokenEntity());
|
||||
|
||||
/** @var AbstractGrant $grantMock */
|
||||
$grantMock = $this->getMockForAbstractClass(AbstractGrant::class);
|
||||
@@ -266,12 +370,12 @@ class AbstractGrantTest extends \PHPUnit_Framework_TestCase
|
||||
[new ScopeEntity()]
|
||||
);
|
||||
$this->assertTrue($accessToken instanceof AccessTokenEntityInterface);
|
||||
$this->assertFalse($accessToken->isExpired());
|
||||
}
|
||||
|
||||
public function testIssueAuthCode()
|
||||
{
|
||||
$authCodeRepoMock = $this->getMock(AuthCodeRepositoryInterface::class);
|
||||
$authCodeRepoMock = $this->getMockBuilder(AuthCodeRepositoryInterface::class)->getMock();
|
||||
$authCodeRepoMock->expects($this->once())->method('getNewAuthCode')->willReturn(new AuthCodeEntity());
|
||||
|
||||
/** @var AbstractGrant $grantMock */
|
||||
$grantMock = $this->getMockForAbstractClass(AbstractGrant::class);
|
||||
@@ -339,7 +443,7 @@ class AbstractGrantTest extends \PHPUnit_Framework_TestCase
|
||||
$grantMock = $this->getMockForAbstractClass(AbstractGrant::class);
|
||||
$grantMock->setScopeRepository($scopeRepositoryMock);
|
||||
|
||||
$this->assertEquals([$scope], $grantMock->validateScopes('basic ', new ClientEntity()));
|
||||
$this->assertEquals([$scope], $grantMock->validateScopes('basic '));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -354,7 +458,7 @@ class AbstractGrantTest extends \PHPUnit_Framework_TestCase
|
||||
$grantMock = $this->getMockForAbstractClass(AbstractGrant::class);
|
||||
$grantMock->setScopeRepository($scopeRepositoryMock);
|
||||
|
||||
$grantMock->validateScopes('basic ', new ClientEntity());
|
||||
$grantMock->validateScopes('basic ');
|
||||
}
|
||||
|
||||
public function testGenerateUniqueIdentifier()
|
||||
@@ -367,4 +471,28 @@ class AbstractGrantTest extends \PHPUnit_Framework_TestCase
|
||||
|
||||
$this->assertTrue(is_string($method->invoke($grantMock)));
|
||||
}
|
||||
|
||||
public function testCanRespondToAuthorizationRequest()
|
||||
{
|
||||
$grantMock = $this->getMockForAbstractClass(AbstractGrant::class);
|
||||
$this->assertFalse($grantMock->canRespondToAuthorizationRequest(new ServerRequest()));
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \LogicException
|
||||
*/
|
||||
public function testValidateAuthorizationRequest()
|
||||
{
|
||||
$grantMock = $this->getMockForAbstractClass(AbstractGrant::class);
|
||||
$grantMock->validateAuthorizationRequest(new ServerRequest());
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \LogicException
|
||||
*/
|
||||
public function testCompleteAuthorizationRequest()
|
||||
{
|
||||
$grantMock = $this->getMockForAbstractClass(AbstractGrant::class);
|
||||
$grantMock->completeAuthorizationRequest(new AuthorizationRequest());
|
||||
}
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
@@ -2,11 +2,12 @@
|
||||
|
||||
namespace LeagueTests\Grant;
|
||||
|
||||
use League\OAuth2\Server\Entities\Interfaces\AccessTokenEntityInterface;
|
||||
use League\OAuth2\Server\Entities\AccessTokenEntityInterface;
|
||||
use League\OAuth2\Server\Grant\ClientCredentialsGrant;
|
||||
use League\OAuth2\Server\Repositories\AccessTokenRepositoryInterface;
|
||||
use League\OAuth2\Server\Repositories\ClientRepositoryInterface;
|
||||
use League\OAuth2\Server\Repositories\ScopeRepositoryInterface;
|
||||
use LeagueTests\Stubs\AccessTokenEntity;
|
||||
use LeagueTests\Stubs\ClientEntity;
|
||||
use LeagueTests\Stubs\StubResponseType;
|
||||
use Zend\Diactoros\ServerRequest;
|
||||
@@ -22,11 +23,11 @@ class ClientCredentialsGrantTest extends \PHPUnit_Framework_TestCase
|
||||
public function testRespondToRequest()
|
||||
{
|
||||
$client = new ClientEntity();
|
||||
$client->setSecret('bar');
|
||||
$clientRepositoryMock = $this->getMockBuilder(ClientRepositoryInterface::class)->getMock();
|
||||
$clientRepositoryMock->method('getClientEntity')->willReturn($client);
|
||||
|
||||
$accessTokenRepositoryMock = $this->getMockBuilder(AccessTokenRepositoryInterface::class)->getMock();
|
||||
$accessTokenRepositoryMock->method('getNewToken')->willReturn(new AccessTokenEntity());
|
||||
$accessTokenRepositoryMock->method('persistNewAccessToken')->willReturnSelf();
|
||||
|
||||
$scopeRepositoryMock = $this->getMockBuilder(ScopeRepositoryInterface::class)->getMock();
|
||||
@@ -46,7 +47,7 @@ class ClientCredentialsGrantTest extends \PHPUnit_Framework_TestCase
|
||||
);
|
||||
|
||||
$responseType = new StubResponseType();
|
||||
$grant->respondToRequest($serverRequest, $responseType, new \DateInterval('PT5M'));
|
||||
$grant->respondToAccessTokenRequest($serverRequest, $responseType, new \DateInterval('PT5M'));
|
||||
|
||||
$this->assertTrue($responseType->getAccessToken() instanceof AccessTokenEntityInterface);
|
||||
}
|
||||
|
@@ -2,19 +2,22 @@
|
||||
|
||||
namespace LeagueTests\Grant;
|
||||
|
||||
use League\OAuth2\Server\CryptKey;
|
||||
use League\OAuth2\Server\Exception\OAuthServerException;
|
||||
use League\OAuth2\Server\Exception\UniqueTokenIdentifierConstraintViolationException;
|
||||
use League\OAuth2\Server\Grant\ImplicitGrant;
|
||||
use League\OAuth2\Server\Repositories\AccessTokenRepositoryInterface;
|
||||
use League\OAuth2\Server\Repositories\ClientRepositoryInterface;
|
||||
use League\OAuth2\Server\Repositories\RefreshTokenRepositoryInterface;
|
||||
use League\OAuth2\Server\Repositories\ScopeRepositoryInterface;
|
||||
use League\OAuth2\Server\Repositories\UserRepositoryInterface;
|
||||
use League\OAuth2\Server\ResponseTypes\HtmlResponse;
|
||||
use League\OAuth2\Server\RequestTypes\AuthorizationRequest;
|
||||
use League\OAuth2\Server\ResponseTypes\RedirectResponse;
|
||||
use LeagueTests\Stubs\AccessTokenEntity;
|
||||
use LeagueTests\Stubs\ClientEntity;
|
||||
use LeagueTests\Stubs\CryptTraitStub;
|
||||
use LeagueTests\Stubs\ScopeEntity;
|
||||
use LeagueTests\Stubs\StubResponseType;
|
||||
use LeagueTests\Stubs\UserEntity;
|
||||
use Zend\Diactoros\Response;
|
||||
use Zend\Diactoros\ServerRequest;
|
||||
|
||||
class ImplicitGrantTest extends \PHPUnit_Framework_TestCase
|
||||
@@ -31,14 +34,35 @@ class ImplicitGrantTest extends \PHPUnit_Framework_TestCase
|
||||
|
||||
public function testGetIdentifier()
|
||||
{
|
||||
$grant = new ImplicitGrant($this->getMock(UserRepositoryInterface::class));
|
||||
|
||||
$grant = new ImplicitGrant(new \DateInterval('PT10M'));
|
||||
$this->assertEquals('implicit', $grant->getIdentifier());
|
||||
}
|
||||
|
||||
public function testCanRespondToRequest()
|
||||
public function testCanRespondToAccessTokenRequest()
|
||||
{
|
||||
$grant = new ImplicitGrant($this->getMock(UserRepositoryInterface::class));
|
||||
$grant = new ImplicitGrant(new \DateInterval('PT10M'));
|
||||
|
||||
$this->assertFalse(
|
||||
$grant->canRespondToAccessTokenRequest(new ServerRequest())
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \LogicException
|
||||
*/
|
||||
public function testRespondToAccessTokenRequest()
|
||||
{
|
||||
$grant = new ImplicitGrant(new \DateInterval('PT10M'));
|
||||
$grant->respondToAccessTokenRequest(
|
||||
new ServerRequest(),
|
||||
new StubResponseType(),
|
||||
new \DateInterval('PT10M')
|
||||
);
|
||||
}
|
||||
|
||||
public function testCanRespondToAuthorizationRequest()
|
||||
{
|
||||
$grant = new ImplicitGrant(new \DateInterval('PT10M'));
|
||||
|
||||
$request = new ServerRequest(
|
||||
[],
|
||||
@@ -46,389 +70,346 @@ class ImplicitGrantTest extends \PHPUnit_Framework_TestCase
|
||||
null,
|
||||
null,
|
||||
'php://input',
|
||||
[],
|
||||
[],
|
||||
[
|
||||
$headers = [],
|
||||
$cookies = [],
|
||||
$queryParams = [
|
||||
'response_type' => 'token',
|
||||
'client_id' => 'foo',
|
||||
]
|
||||
);
|
||||
|
||||
$this->assertTrue($grant->canRespondToRequest($request));
|
||||
$this->assertTrue($grant->canRespondToAuthorizationRequest($request));
|
||||
}
|
||||
|
||||
public function testRespondToAuthorizationRequest()
|
||||
public function testValidateAuthorizationRequest()
|
||||
{
|
||||
$client = new ClientEntity();
|
||||
$client->setRedirectUri('http://foo/bar');
|
||||
$clientRepositoryMock = $this->getMockBuilder(ClientRepositoryInterface::class)->getMock();
|
||||
$clientRepositoryMock->method('getClientEntity')->willReturn($client);
|
||||
|
||||
$userRepositoryMock = $this->getMockBuilder(UserRepositoryInterface::class)->getMock();
|
||||
$userEntity = new UserEntity();
|
||||
$userRepositoryMock->method('getUserEntityByUserCredentials')->willReturn($userEntity);
|
||||
|
||||
$accessTokenRepositoryMock = $this->getMockBuilder(AccessTokenRepositoryInterface::class)->getMock();
|
||||
$accessTokenRepositoryMock->method('persistNewAccessToken')->willReturnSelf();
|
||||
|
||||
$scopeRepositoryMock = $this->getMockBuilder(ScopeRepositoryInterface::class)->getMock();
|
||||
$scopeEntity = new ScopeEntity();
|
||||
$scopeRepositoryMock->method('getScopeEntityByIdentifier')->willReturn($scopeEntity);
|
||||
$scopeRepositoryMock->method('finalizeScopes')->willReturnArgument(0);
|
||||
|
||||
$grant = new ImplicitGrant($userRepositoryMock);
|
||||
$grant = new ImplicitGrant(new \DateInterval('PT10M'));
|
||||
$grant->setClientRepository($clientRepositoryMock);
|
||||
$grant->setAccessTokenRepository($accessTokenRepositoryMock);
|
||||
$grant->setScopeRepository($scopeRepositoryMock);
|
||||
$grant->setPublicKeyPath('file://' . __DIR__ . '/../Stubs/public.key');
|
||||
$grant->setPrivateKeyPath('file://' . __DIR__ . '/../Stubs/private.key');
|
||||
|
||||
$request = new ServerRequest(
|
||||
[
|
||||
'HTTP_HOST' => 'auth-server.tld',
|
||||
'REQUEST_URI' => '/authorize',
|
||||
],
|
||||
[],
|
||||
[],
|
||||
null,
|
||||
'POST',
|
||||
null,
|
||||
'php://input',
|
||||
[],
|
||||
[],
|
||||
[
|
||||
'response_type' => 'token',
|
||||
$headers = [],
|
||||
$cookies = [],
|
||||
$queryParams = [
|
||||
'response_type' => 'code',
|
||||
'client_id' => 'foo',
|
||||
'state' => 'foobar',
|
||||
],
|
||||
[
|
||||
'username' => 'alex',
|
||||
'password' => 'whisky',
|
||||
'action' => 'approve',
|
||||
'redirect_uri' => 'http://foo/bar',
|
||||
]
|
||||
);
|
||||
|
||||
$response = $grant->respondToRequest($request, new StubResponseType(), new \DateInterval('PT10M'));
|
||||
$this->assertTrue($grant->validateAuthorizationRequest($request) instanceof AuthorizationRequest);
|
||||
}
|
||||
|
||||
$this->assertTrue($response instanceof RedirectResponse);
|
||||
public function testValidateAuthorizationRequestRedirectUriArray()
|
||||
{
|
||||
$client = new ClientEntity();
|
||||
$client->setRedirectUri(['http://foo/bar']);
|
||||
$clientRepositoryMock = $this->getMockBuilder(ClientRepositoryInterface::class)->getMock();
|
||||
$clientRepositoryMock->method('getClientEntity')->willReturn($client);
|
||||
|
||||
$scopeRepositoryMock = $this->getMockBuilder(ScopeRepositoryInterface::class)->getMock();
|
||||
$scopeEntity = new ScopeEntity();
|
||||
$scopeRepositoryMock->method('getScopeEntityByIdentifier')->willReturn($scopeEntity);
|
||||
$scopeRepositoryMock->method('finalizeScopes')->willReturnArgument(0);
|
||||
|
||||
$grant = new ImplicitGrant(new \DateInterval('PT10M'));
|
||||
$grant->setClientRepository($clientRepositoryMock);
|
||||
$grant->setScopeRepository($scopeRepositoryMock);
|
||||
|
||||
$request = new ServerRequest(
|
||||
[],
|
||||
[],
|
||||
null,
|
||||
null,
|
||||
'php://input',
|
||||
$headers = [],
|
||||
$cookies = [],
|
||||
$queryParams = [
|
||||
'response_type' => 'code',
|
||||
'client_id' => 'foo',
|
||||
'redirect_uri' => 'http://foo/bar',
|
||||
]
|
||||
);
|
||||
|
||||
$this->assertTrue($grant->validateAuthorizationRequest($request) instanceof AuthorizationRequest);
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \League\OAuth2\Server\Exception\OAuthServerException
|
||||
* @expectedExceptionCode 3
|
||||
*/
|
||||
public function testRespondToAuthorizationRequestMissingClientId()
|
||||
public function testValidateAuthorizationRequestMissingClientId()
|
||||
{
|
||||
$grant = new ImplicitGrant($this->getMock(UserRepositoryInterface::class));
|
||||
$grant->setPublicKeyPath('file://' . __DIR__ . '/../Stubs/public.key');
|
||||
$grant->setPrivateKeyPath('file://' . __DIR__ . '/../Stubs/private.key');
|
||||
|
||||
$request = new ServerRequest(
|
||||
[
|
||||
'HTTP_HOST' => 'auth-server.tld',
|
||||
'REQUEST_URI' => '/authorize',
|
||||
],
|
||||
[],
|
||||
null,
|
||||
'POST',
|
||||
'php://input',
|
||||
[],
|
||||
[
|
||||
'oauth_authorize_request' => $this->cryptStub->doEncrypt(json_encode(['user_id' => 123])),
|
||||
],
|
||||
[
|
||||
'response_type' => 'token',
|
||||
],
|
||||
[
|
||||
'username' => 'alex',
|
||||
'password' => 'whisky',
|
||||
'action' => 'approve',
|
||||
]
|
||||
);
|
||||
|
||||
$grant->respondToRequest($request, new StubResponseType(), new \DateInterval('PT10M'));
|
||||
}
|
||||
|
||||
public function testRespondToAuthorizationRequestBadClient()
|
||||
{
|
||||
$client = null;
|
||||
$clientRepositoryMock = $this->getMockBuilder(ClientRepositoryInterface::class)->getMock();
|
||||
$clientRepositoryMock->method('getClientEntity')->willReturn($client);
|
||||
|
||||
$grant = new ImplicitGrant($this->getMock(UserRepositoryInterface::class));
|
||||
$grant = new ImplicitGrant(new \DateInterval('PT10M'));
|
||||
$grant->setClientRepository($clientRepositoryMock);
|
||||
$grant->setPublicKeyPath('file://' . __DIR__ . '/../Stubs/public.key');
|
||||
$grant->setPrivateKeyPath('file://' . __DIR__ . '/../Stubs/private.key');
|
||||
|
||||
$request = new ServerRequest(
|
||||
[
|
||||
'HTTP_HOST' => 'auth-server.tld',
|
||||
'REQUEST_URI' => '/authorize',
|
||||
],
|
||||
[],
|
||||
[],
|
||||
null,
|
||||
'POST',
|
||||
null,
|
||||
'php://input',
|
||||
[],
|
||||
[
|
||||
'oauth_authorize_request' => $this->cryptStub->doEncrypt(json_encode(['user_id' => 123])),
|
||||
],
|
||||
[
|
||||
'response_type' => 'token',
|
||||
'client_id' => 'foo',
|
||||
],
|
||||
[
|
||||
'username' => 'alex',
|
||||
'password' => 'whisky',
|
||||
'action' => 'approve',
|
||||
$headers = [],
|
||||
$cookies = [],
|
||||
$queryParams = [
|
||||
'response_type' => 'code',
|
||||
]
|
||||
);
|
||||
|
||||
try {
|
||||
/* @var StubResponseType $response */
|
||||
$grant->respondToRequest($request, new StubResponseType(), new \DateInterval('PT10M'));
|
||||
} catch (OAuthServerException $e) {
|
||||
$this->assertEquals($e->getMessage(), 'Client authentication failed');
|
||||
}
|
||||
}
|
||||
|
||||
public function testRespondToAuthorizationRequestBadRedirectUri()
|
||||
{
|
||||
$client = new ClientEntity();
|
||||
$clientRepositoryMock = $this->getMockBuilder(ClientRepositoryInterface::class)->getMock();
|
||||
$clientRepositoryMock->method('getClientEntity')->willReturn($client);
|
||||
|
||||
$userRepositoryMock = $this->getMockBuilder(UserRepositoryInterface::class)->getMock();
|
||||
$userEntity = new UserEntity();
|
||||
$userRepositoryMock->method('getUserEntityByUserCredentials')->willReturn($userEntity);
|
||||
|
||||
$grant = new ImplicitGrant($this->getMock(UserRepositoryInterface::class));
|
||||
$grant->setClientRepository($clientRepositoryMock);
|
||||
$grant->setPublicKeyPath('file://' . __DIR__ . '/../Stubs/public.key');
|
||||
$grant->setPrivateKeyPath('file://' . __DIR__ . '/../Stubs/private.key');
|
||||
|
||||
$request = new ServerRequest(
|
||||
[
|
||||
'HTTP_HOST' => 'auth-server.tld',
|
||||
'REQUEST_URI' => '/authorize',
|
||||
],
|
||||
[],
|
||||
null,
|
||||
'POST',
|
||||
'php://input',
|
||||
[],
|
||||
[
|
||||
'oauth_authorize_request' => $this->cryptStub->doEncrypt(json_encode(['user_id' => 123])),
|
||||
],
|
||||
[
|
||||
'response_type' => 'token',
|
||||
'client_id' => 'foo',
|
||||
'redirect_uri' => 'sdfsdf',
|
||||
],
|
||||
[
|
||||
'username' => 'alex',
|
||||
'password' => 'whisky',
|
||||
'action' => 'approve',
|
||||
]
|
||||
);
|
||||
|
||||
try {
|
||||
/* @var StubResponseType $response */
|
||||
$grant->respondToRequest($request, new StubResponseType(), new \DateInterval('PT10M'));
|
||||
} catch (OAuthServerException $e) {
|
||||
$this->assertEquals($e->getMessage(), 'Client authentication failed');
|
||||
}
|
||||
$grant->validateAuthorizationRequest($request);
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \League\OAuth2\Server\Exception\OAuthServerException
|
||||
* @expectedExceptionCode 7
|
||||
* @expectedExceptionCode 4
|
||||
*/
|
||||
public function testRespondToAuthorizationRequestBadCookie()
|
||||
public function testValidateAuthorizationRequestInvalidClientId()
|
||||
{
|
||||
$client = new ClientEntity();
|
||||
$client->setRedirectUri('http://foo/bar');
|
||||
$clientRepositoryMock = $this->getMockBuilder(ClientRepositoryInterface::class)->getMock();
|
||||
$clientRepositoryMock->method('getClientEntity')->willReturn($client);
|
||||
$clientRepositoryMock->method('getClientEntity')->willReturn(null);
|
||||
|
||||
$userRepositoryMock = $this->getMockBuilder(UserRepositoryInterface::class)->getMock();
|
||||
$userEntity = new UserEntity();
|
||||
$userRepositoryMock->method('getUserEntityByUserCredentials')->willReturn($userEntity);
|
||||
|
||||
$grant = new ImplicitGrant($this->getMock(UserRepositoryInterface::class));
|
||||
$grant = new ImplicitGrant(new \DateInterval('PT10M'));
|
||||
$grant->setClientRepository($clientRepositoryMock);
|
||||
$grant->setPublicKeyPath('file://' . __DIR__ . '/../Stubs/public.key');
|
||||
$grant->setPrivateKeyPath('file://' . __DIR__ . '/../Stubs/private.key');
|
||||
|
||||
$request = new ServerRequest(
|
||||
[
|
||||
'HTTP_HOST' => 'auth-server.tld',
|
||||
'REQUEST_URI' => '/authorize',
|
||||
],
|
||||
[],
|
||||
[],
|
||||
null,
|
||||
'POST',
|
||||
'php://input',
|
||||
[],
|
||||
[
|
||||
'oauth_authorize_request' => 'blah',
|
||||
],
|
||||
[
|
||||
'response_type' => 'token',
|
||||
'client_id' => 'foo',
|
||||
],
|
||||
[
|
||||
'username' => 'alex',
|
||||
'password' => 'whisky',
|
||||
'action' => 'approve',
|
||||
]
|
||||
);
|
||||
|
||||
$grant->respondToRequest($request, new StubResponseType(), new \DateInterval('PT10M'));
|
||||
}
|
||||
|
||||
public function testRespondToAuthorizationRequestTryLogin()
|
||||
{
|
||||
$client = new ClientEntity();
|
||||
$client->setRedirectUri('http://foo/bar');
|
||||
$clientRepositoryMock = $this->getMockBuilder(ClientRepositoryInterface::class)->getMock();
|
||||
$clientRepositoryMock->method('getClientEntity')->willReturn($client);
|
||||
|
||||
$userRepositoryMock = $this->getMockBuilder(UserRepositoryInterface::class)->getMock();
|
||||
$userEntity = new UserEntity();
|
||||
$userRepositoryMock->method('getUserEntityByUserCredentials')->willReturn($userEntity);
|
||||
|
||||
$accessTokenRepositoryMock = $this->getMockBuilder(AccessTokenRepositoryInterface::class)->getMock();
|
||||
$accessTokenRepositoryMock->method('persistNewAccessToken')->willReturnSelf();
|
||||
|
||||
$grant = new ImplicitGrant($this->getMock(UserRepositoryInterface::class));
|
||||
$grant->setClientRepository($clientRepositoryMock);
|
||||
$grant->setAccessTokenRepository($accessTokenRepositoryMock);
|
||||
$grant->setPublicKeyPath('file://' . __DIR__ . '/../Stubs/public.key');
|
||||
$grant->setPrivateKeyPath('file://' . __DIR__ . '/../Stubs/private.key');
|
||||
|
||||
$request = new ServerRequest(
|
||||
[
|
||||
'HTTP_HOST' => 'auth-server.tld',
|
||||
'REQUEST_URI' => '/authorize',
|
||||
],
|
||||
[],
|
||||
null,
|
||||
'POST',
|
||||
'php://input',
|
||||
[],
|
||||
[
|
||||
'oauth_authorize_request' => $this->cryptStub->doEncrypt(json_encode(['user_id' => null])),
|
||||
],
|
||||
[
|
||||
'response_type' => 'token',
|
||||
'client_id' => 'foo',
|
||||
],
|
||||
[
|
||||
'username' => 'alex',
|
||||
'password' => 'whisky',
|
||||
'action' => 'approve',
|
||||
]
|
||||
);
|
||||
|
||||
$response = $grant->respondToRequest($request, new StubResponseType(), new \DateInterval('PT10M'));
|
||||
$this->assertTrue($response instanceof HtmlResponse);
|
||||
|
||||
$response = $response->generateHttpResponse(new Response);
|
||||
$this->assertTrue(strstr((string) $response->getBody(), 'Incorrect username or password') !== false);
|
||||
}
|
||||
|
||||
public function testRespondToAuthorizationRequestShowAuthorizeForm()
|
||||
{
|
||||
$client = new ClientEntity();
|
||||
$client->setRedirectUri('http://foo/bar');
|
||||
$clientRepositoryMock = $this->getMockBuilder(ClientRepositoryInterface::class)->getMock();
|
||||
$clientRepositoryMock->method('getClientEntity')->willReturn($client);
|
||||
|
||||
$userRepositoryMock = $this->getMockBuilder(UserRepositoryInterface::class)->getMock();
|
||||
$userEntity = new UserEntity();
|
||||
$userRepositoryMock->method('getUserEntityByUserCredentials')->willReturn($userEntity);
|
||||
|
||||
$accessTokenRepositoryMock = $this->getMockBuilder(AccessTokenRepositoryInterface::class)->getMock();
|
||||
$accessTokenRepositoryMock->method('persistNewAccessToken')->willReturnSelf();
|
||||
|
||||
$grant = new ImplicitGrant($this->getMock(UserRepositoryInterface::class));
|
||||
$grant->setClientRepository($clientRepositoryMock);
|
||||
$grant->setAccessTokenRepository($accessTokenRepositoryMock);
|
||||
$grant->setPublicKeyPath('file://' . __DIR__ . '/../Stubs/public.key');
|
||||
$grant->setPrivateKeyPath('file://' . __DIR__ . '/../Stubs/private.key');
|
||||
|
||||
$request = new ServerRequest(
|
||||
[
|
||||
'HTTP_HOST' => 'auth-server.tld',
|
||||
'REQUEST_URI' => '/authorize',
|
||||
],
|
||||
[],
|
||||
null,
|
||||
'POST',
|
||||
'php://input',
|
||||
[],
|
||||
[
|
||||
'oauth_authorize_request' => $this->cryptStub->doEncrypt(json_encode(['user_id' => 123])),
|
||||
],
|
||||
[
|
||||
$headers = [],
|
||||
$cookies = [],
|
||||
$queryParams = [
|
||||
'response_type' => 'code',
|
||||
'client_id' => 'foo',
|
||||
],
|
||||
[
|
||||
'username' => 'alex',
|
||||
'password' => 'whisky',
|
||||
]
|
||||
);
|
||||
|
||||
$response = $grant->respondToRequest($request, new StubResponseType(), new \DateInterval('PT10M'));
|
||||
$grant->validateAuthorizationRequest($request);
|
||||
}
|
||||
|
||||
$this->assertTrue($response instanceof HtmlResponse);
|
||||
/**
|
||||
* @expectedException \League\OAuth2\Server\Exception\OAuthServerException
|
||||
* @expectedExceptionCode 4
|
||||
*/
|
||||
public function testValidateAuthorizationRequestBadRedirectUriString()
|
||||
{
|
||||
$client = new ClientEntity();
|
||||
$client->setRedirectUri('http://foo/bar');
|
||||
$clientRepositoryMock = $this->getMockBuilder(ClientRepositoryInterface::class)->getMock();
|
||||
$clientRepositoryMock->method('getClientEntity')->willReturn($client);
|
||||
|
||||
$response = $response->generateHttpResponse(new Response);
|
||||
$this->assertTrue(strstr($response->getHeader('set-cookie')[0], 'oauth_authorize_request') !== false);
|
||||
$grant = new ImplicitGrant(new \DateInterval('PT10M'));
|
||||
$grant->setClientRepository($clientRepositoryMock);
|
||||
|
||||
$request = new ServerRequest(
|
||||
[],
|
||||
[],
|
||||
null,
|
||||
null,
|
||||
'php://input',
|
||||
$headers = [],
|
||||
$cookies = [],
|
||||
$queryParams = [
|
||||
'response_type' => 'code',
|
||||
'client_id' => 'foo',
|
||||
'redirect_uri' => 'http://bar',
|
||||
]
|
||||
);
|
||||
|
||||
$grant->validateAuthorizationRequest($request);
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \League\OAuth2\Server\Exception\OAuthServerException
|
||||
* @expectedExceptionCode 4
|
||||
*/
|
||||
public function testValidateAuthorizationRequestBadRedirectUriArray()
|
||||
{
|
||||
$client = new ClientEntity();
|
||||
$client->setRedirectUri(['http://foo/bar']);
|
||||
$clientRepositoryMock = $this->getMockBuilder(ClientRepositoryInterface::class)->getMock();
|
||||
$clientRepositoryMock->method('getClientEntity')->willReturn($client);
|
||||
|
||||
$grant = new ImplicitGrant(new \DateInterval('PT10M'));
|
||||
$grant->setClientRepository($clientRepositoryMock);
|
||||
|
||||
$request = new ServerRequest(
|
||||
[],
|
||||
[],
|
||||
null,
|
||||
null,
|
||||
'php://input',
|
||||
$headers = [],
|
||||
$cookies = [],
|
||||
$queryParams = [
|
||||
'response_type' => 'code',
|
||||
'client_id' => 'foo',
|
||||
'redirect_uri' => 'http://bar',
|
||||
]
|
||||
);
|
||||
|
||||
$grant->validateAuthorizationRequest($request);
|
||||
}
|
||||
|
||||
public function testCompleteAuthorizationRequest()
|
||||
{
|
||||
$authRequest = new AuthorizationRequest();
|
||||
$authRequest->setAuthorizationApproved(true);
|
||||
$authRequest->setClient(new ClientEntity());
|
||||
$authRequest->setGrantTypeId('authorization_code');
|
||||
$authRequest->setUser(new UserEntity());
|
||||
|
||||
$accessTokenRepositoryMock = $this->getMockBuilder(AccessTokenRepositoryInterface::class)->getMock();
|
||||
$accessTokenRepositoryMock->method('getNewToken')->willReturn(new AccessTokenEntity());
|
||||
$accessTokenRepositoryMock->method('persistNewAccessToken')->willReturnSelf();
|
||||
|
||||
$grant = new ImplicitGrant(new \DateInterval('PT10M'));
|
||||
$grant->setPrivateKey(new CryptKey('file://' . __DIR__ . '/../Stubs/private.key'));
|
||||
$grant->setPublicKey(new CryptKey('file://' . __DIR__ . '/../Stubs/public.key'));
|
||||
$grant->setAccessTokenRepository($accessTokenRepositoryMock);
|
||||
|
||||
$this->assertTrue($grant->completeAuthorizationRequest($authRequest) instanceof RedirectResponse);
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \League\OAuth2\Server\Exception\OAuthServerException
|
||||
* @expectedExceptionCode 9
|
||||
*/
|
||||
public function testRespondToAuthorizationRequestUserDenied()
|
||||
public function testCompleteAuthorizationRequestDenied()
|
||||
{
|
||||
$client = new ClientEntity();
|
||||
$client->setRedirectUri('http://foo/bar');
|
||||
$clientRepositoryMock = $this->getMockBuilder(ClientRepositoryInterface::class)->getMock();
|
||||
$clientRepositoryMock->method('getClientEntity')->willReturn($client);
|
||||
$authRequest = new AuthorizationRequest();
|
||||
$authRequest->setAuthorizationApproved(false);
|
||||
$authRequest->setClient(new ClientEntity());
|
||||
$authRequest->setGrantTypeId('authorization_code');
|
||||
$authRequest->setUser(new UserEntity());
|
||||
|
||||
$userRepositoryMock = $this->getMockBuilder(UserRepositoryInterface::class)->getMock();
|
||||
$userEntity = new UserEntity();
|
||||
$userRepositoryMock->method('getUserEntityByUserCredentials')->willReturn($userEntity);
|
||||
$accessTokenRepositoryMock = $this->getMockBuilder(AccessTokenRepositoryInterface::class)->getMock();
|
||||
$accessTokenRepositoryMock->method('getNewToken')->willReturn(new AccessTokenEntity());
|
||||
$accessTokenRepositoryMock->method('persistNewAccessToken')->willReturnSelf();
|
||||
|
||||
$grant = new ImplicitGrant($this->getMock(UserRepositoryInterface::class));
|
||||
$grant->setClientRepository($clientRepositoryMock);
|
||||
$grant->setPublicKeyPath('file://' . __DIR__ . '/../Stubs/public.key');
|
||||
$grant->setPrivateKeyPath('file://' . __DIR__ . '/../Stubs/private.key');
|
||||
$grant = new ImplicitGrant(new \DateInterval('PT10M'));
|
||||
$grant->setPrivateKey(new CryptKey('file://' . __DIR__ . '/../Stubs/private.key'));
|
||||
$grant->setPublicKey(new CryptKey('file://' . __DIR__ . '/../Stubs/public.key'));
|
||||
$grant->setAccessTokenRepository($accessTokenRepositoryMock);
|
||||
|
||||
$request = new ServerRequest(
|
||||
[
|
||||
'HTTP_HOST' => 'auth-server.tld',
|
||||
'REQUEST_URI' => '/authorize',
|
||||
],
|
||||
[],
|
||||
null,
|
||||
'POST',
|
||||
'php://input',
|
||||
[],
|
||||
[
|
||||
'oauth_authorize_request' => $this->cryptStub->doEncrypt(json_encode(['user_id' => 123])),
|
||||
],
|
||||
[
|
||||
'response_type' => 'code',
|
||||
'client_id' => 'foo',
|
||||
'state' => 'foobar',
|
||||
],
|
||||
[
|
||||
'username' => 'alex',
|
||||
'password' => 'whisky',
|
||||
'action' => 'denied',
|
||||
]
|
||||
);
|
||||
$grant->completeAuthorizationRequest($authRequest);
|
||||
}
|
||||
|
||||
$grant->respondToRequest($request, new StubResponseType(), new \DateInterval('PT10M'));
|
||||
public function testAccessTokenRepositoryUniqueConstraintCheck()
|
||||
{
|
||||
$authRequest = new AuthorizationRequest();
|
||||
$authRequest->setAuthorizationApproved(true);
|
||||
$authRequest->setClient(new ClientEntity());
|
||||
$authRequest->setGrantTypeId('authorization_code');
|
||||
$authRequest->setUser(new UserEntity());
|
||||
|
||||
/** @var AccessTokenRepositoryInterface|\PHPUnit_Framework_MockObject_MockObject $accessTokenRepositoryMock */
|
||||
$accessTokenRepositoryMock = $this->getMockBuilder(AccessTokenRepositoryInterface::class)->getMock();
|
||||
$accessTokenRepositoryMock->method('getNewToken')->willReturn(new AccessTokenEntity());
|
||||
$accessTokenRepositoryMock->expects($this->at(0))->method('persistNewAccessToken')->willThrowException(UniqueTokenIdentifierConstraintViolationException::create());
|
||||
$accessTokenRepositoryMock->expects($this->at(1))->method('persistNewAccessToken')->willReturnSelf();
|
||||
|
||||
$grant = new ImplicitGrant(new \DateInterval('PT10M'));
|
||||
$grant->setPrivateKey(new CryptKey('file://' . __DIR__ . '/../Stubs/private.key'));
|
||||
$grant->setPublicKey(new CryptKey('file://' . __DIR__ . '/../Stubs/public.key'));
|
||||
$grant->setAccessTokenRepository($accessTokenRepositoryMock);
|
||||
|
||||
$this->assertTrue($grant->completeAuthorizationRequest($authRequest) instanceof RedirectResponse);
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \League\OAuth2\Server\Exception\OAuthServerException
|
||||
* @expectedExceptionCode 7
|
||||
*/
|
||||
public function testAccessTokenRepositoryFailToPersist()
|
||||
{
|
||||
$authRequest = new AuthorizationRequest();
|
||||
$authRequest->setAuthorizationApproved(true);
|
||||
$authRequest->setClient(new ClientEntity());
|
||||
$authRequest->setGrantTypeId('authorization_code');
|
||||
$authRequest->setUser(new UserEntity());
|
||||
|
||||
/** @var AccessTokenRepositoryInterface|\PHPUnit_Framework_MockObject_MockObject $accessTokenRepositoryMock */
|
||||
$accessTokenRepositoryMock = $this->getMockBuilder(AccessTokenRepositoryInterface::class)->getMock();
|
||||
$accessTokenRepositoryMock->method('getNewToken')->willReturn(new AccessTokenEntity());
|
||||
$accessTokenRepositoryMock->method('persistNewAccessToken')->willThrowException(OAuthServerException::serverError('something bad happened'));
|
||||
|
||||
$grant = new ImplicitGrant(new \DateInterval('PT10M'));
|
||||
$grant->setPrivateKey(new CryptKey('file://' . __DIR__ . '/../Stubs/private.key'));
|
||||
$grant->setPublicKey(new CryptKey('file://' . __DIR__ . '/../Stubs/public.key'));
|
||||
$grant->setAccessTokenRepository($accessTokenRepositoryMock);
|
||||
|
||||
$grant->completeAuthorizationRequest($authRequest);
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \League\OAuth2\Server\Exception\UniqueTokenIdentifierConstraintViolationException
|
||||
* @expectedExceptionCode 100
|
||||
*/
|
||||
public function testAccessTokenRepositoryFailToPersistUniqueNoInfiniteLoop()
|
||||
{
|
||||
$authRequest = new AuthorizationRequest();
|
||||
$authRequest->setAuthorizationApproved(true);
|
||||
$authRequest->setClient(new ClientEntity());
|
||||
$authRequest->setGrantTypeId('authorization_code');
|
||||
$authRequest->setUser(new UserEntity());
|
||||
|
||||
/** @var AccessTokenRepositoryInterface|\PHPUnit_Framework_MockObject_MockObject $accessTokenRepositoryMock */
|
||||
$accessTokenRepositoryMock = $this->getMockBuilder(AccessTokenRepositoryInterface::class)->getMock();
|
||||
$accessTokenRepositoryMock->method('getNewToken')->willReturn(new AccessTokenEntity());
|
||||
$accessTokenRepositoryMock->method('persistNewAccessToken')->willThrowException(UniqueTokenIdentifierConstraintViolationException::create());
|
||||
|
||||
$grant = new ImplicitGrant(new \DateInterval('PT10M'));
|
||||
$grant->setPrivateKey(new CryptKey('file://' . __DIR__ . '/../Stubs/private.key'));
|
||||
$grant->setPublicKey(new CryptKey('file://' . __DIR__ . '/../Stubs/public.key'));
|
||||
$grant->setAccessTokenRepository($accessTokenRepositoryMock);
|
||||
|
||||
$grant->completeAuthorizationRequest($authRequest);
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \LogicException
|
||||
*/
|
||||
public function testSetRefreshTokenTTL()
|
||||
{
|
||||
$grant = new ImplicitGrant(new \DateInterval('PT10M'));
|
||||
$grant->setRefreshTokenTTL(new \DateInterval('PT10M'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \LogicException
|
||||
*/
|
||||
public function testSetRefreshTokenRepository()
|
||||
{
|
||||
$grant = new ImplicitGrant(new \DateInterval('PT10M'));
|
||||
$refreshTokenRepositoryMock = $this->getMockBuilder(RefreshTokenRepositoryInterface::class)->getMock();
|
||||
$grant->setRefreshTokenRepository($refreshTokenRepositoryMock);
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \LogicException
|
||||
*/
|
||||
public function testCompleteAuthorizationRequestNoUser()
|
||||
{
|
||||
$grant = new ImplicitGrant(new \DateInterval('PT10M'));
|
||||
$grant->completeAuthorizationRequest(new AuthorizationRequest());
|
||||
}
|
||||
}
|
||||
|
@@ -2,15 +2,17 @@
|
||||
|
||||
namespace LeagueTests\Grant;
|
||||
|
||||
use League\OAuth2\Server\Entities\Interfaces\AccessTokenEntityInterface;
|
||||
use League\OAuth2\Server\Entities\Interfaces\RefreshTokenEntityInterface;
|
||||
use League\OAuth2\Server\Entities\AccessTokenEntityInterface;
|
||||
use League\OAuth2\Server\Entities\RefreshTokenEntityInterface;
|
||||
use League\OAuth2\Server\Grant\PasswordGrant;
|
||||
use League\OAuth2\Server\Repositories\AccessTokenRepositoryInterface;
|
||||
use League\OAuth2\Server\Repositories\ClientRepositoryInterface;
|
||||
use League\OAuth2\Server\Repositories\RefreshTokenRepositoryInterface;
|
||||
use League\OAuth2\Server\Repositories\ScopeRepositoryInterface;
|
||||
use League\OAuth2\Server\Repositories\UserRepositoryInterface;
|
||||
use LeagueTests\Stubs\AccessTokenEntity;
|
||||
use LeagueTests\Stubs\ClientEntity;
|
||||
use LeagueTests\Stubs\RefreshTokenEntity;
|
||||
use LeagueTests\Stubs\StubResponseType;
|
||||
use LeagueTests\Stubs\UserEntity;
|
||||
use Zend\Diactoros\ServerRequest;
|
||||
@@ -19,8 +21,8 @@ class PasswordGrantTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
public function testGetIdentifier()
|
||||
{
|
||||
$userRepositoryMock = $this->getMock(UserRepositoryInterface::class);
|
||||
$refreshTokenRepositoryMock = $this->getMock(RefreshTokenRepositoryInterface::class);
|
||||
$userRepositoryMock = $this->getMockBuilder(UserRepositoryInterface::class)->getMock();
|
||||
$refreshTokenRepositoryMock = $this->getMockBuilder(RefreshTokenRepositoryInterface::class)->getMock();
|
||||
|
||||
$grant = new PasswordGrant($userRepositoryMock, $refreshTokenRepositoryMock);
|
||||
$this->assertEquals('password', $grant->getIdentifier());
|
||||
@@ -29,11 +31,11 @@ class PasswordGrantTest extends \PHPUnit_Framework_TestCase
|
||||
public function testRespondToRequest()
|
||||
{
|
||||
$client = new ClientEntity();
|
||||
$client->setSecret('bar');
|
||||
$clientRepositoryMock = $this->getMockBuilder(ClientRepositoryInterface::class)->getMock();
|
||||
$clientRepositoryMock->method('getClientEntity')->willReturn($client);
|
||||
|
||||
$accessTokenRepositoryMock = $this->getMockBuilder(AccessTokenRepositoryInterface::class)->getMock();
|
||||
$accessTokenRepositoryMock->method('getNewToken')->willReturn(new AccessTokenEntity());
|
||||
$accessTokenRepositoryMock->method('persistNewAccessToken')->willReturnSelf();
|
||||
|
||||
$userRepositoryMock = $this->getMockBuilder(UserRepositoryInterface::class)->getMock();
|
||||
@@ -42,6 +44,7 @@ class PasswordGrantTest extends \PHPUnit_Framework_TestCase
|
||||
|
||||
$refreshTokenRepositoryMock = $this->getMockBuilder(RefreshTokenRepositoryInterface::class)->getMock();
|
||||
$refreshTokenRepositoryMock->method('persistNewRefreshToken')->willReturnSelf();
|
||||
$refreshTokenRepositoryMock->method('getNewRefreshToken')->willReturn(new RefreshTokenEntity());
|
||||
|
||||
$scopeRepositoryMock = $this->getMockBuilder(ScopeRepositoryInterface::class)->getMock();
|
||||
$scopeRepositoryMock->method('finalizeScopes')->willReturnArgument(0);
|
||||
@@ -62,7 +65,7 @@ class PasswordGrantTest extends \PHPUnit_Framework_TestCase
|
||||
);
|
||||
|
||||
$responseType = new StubResponseType();
|
||||
$grant->respondToRequest($serverRequest, $responseType, new \DateInterval('PT5M'));
|
||||
$grant->respondToAccessTokenRequest($serverRequest, $responseType, new \DateInterval('PT5M'));
|
||||
|
||||
$this->assertTrue($responseType->getAccessToken() instanceof AccessTokenEntityInterface);
|
||||
$this->assertTrue($responseType->getRefreshToken() instanceof RefreshTokenEntityInterface);
|
||||
@@ -74,7 +77,6 @@ class PasswordGrantTest extends \PHPUnit_Framework_TestCase
|
||||
public function testRespondToRequestMissingUsername()
|
||||
{
|
||||
$client = new ClientEntity();
|
||||
$client->setSecret('bar');
|
||||
$clientRepositoryMock = $this->getMockBuilder(ClientRepositoryInterface::class)->getMock();
|
||||
$clientRepositoryMock->method('getClientEntity')->willReturn($client);
|
||||
|
||||
@@ -97,7 +99,7 @@ class PasswordGrantTest extends \PHPUnit_Framework_TestCase
|
||||
);
|
||||
|
||||
$responseType = new StubResponseType();
|
||||
$grant->respondToRequest($serverRequest, $responseType, new \DateInterval('PT5M'));
|
||||
$grant->respondToAccessTokenRequest($serverRequest, $responseType, new \DateInterval('PT5M'));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -106,7 +108,6 @@ class PasswordGrantTest extends \PHPUnit_Framework_TestCase
|
||||
public function testRespondToRequestMissingPassword()
|
||||
{
|
||||
$client = new ClientEntity();
|
||||
$client->setSecret('bar');
|
||||
$clientRepositoryMock = $this->getMockBuilder(ClientRepositoryInterface::class)->getMock();
|
||||
$clientRepositoryMock->method('getClientEntity')->willReturn($client);
|
||||
|
||||
@@ -130,7 +131,7 @@ class PasswordGrantTest extends \PHPUnit_Framework_TestCase
|
||||
);
|
||||
|
||||
$responseType = new StubResponseType();
|
||||
$grant->respondToRequest($serverRequest, $responseType, new \DateInterval('PT5M'));
|
||||
$grant->respondToAccessTokenRequest($serverRequest, $responseType, new \DateInterval('PT5M'));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -139,7 +140,6 @@ class PasswordGrantTest extends \PHPUnit_Framework_TestCase
|
||||
public function testRespondToRequestBadCredentials()
|
||||
{
|
||||
$client = new ClientEntity();
|
||||
$client->setSecret('bar');
|
||||
$clientRepositoryMock = $this->getMockBuilder(ClientRepositoryInterface::class)->getMock();
|
||||
$clientRepositoryMock->method('getClientEntity')->willReturn($client);
|
||||
|
||||
@@ -165,6 +165,6 @@ class PasswordGrantTest extends \PHPUnit_Framework_TestCase
|
||||
);
|
||||
|
||||
$responseType = new StubResponseType();
|
||||
$grant->respondToRequest($serverRequest, $responseType, new \DateInterval('PT5M'));
|
||||
$grant->respondToAccessTokenRequest($serverRequest, $responseType, new \DateInterval('PT5M'));
|
||||
}
|
||||
}
|
||||
|
@@ -2,15 +2,18 @@
|
||||
|
||||
namespace LeagueTests\Grant;
|
||||
|
||||
use League\OAuth2\Server\Entities\Interfaces\AccessTokenEntityInterface;
|
||||
use League\OAuth2\Server\Entities\Interfaces\RefreshTokenEntityInterface;
|
||||
use League\OAuth2\Server\CryptKey;
|
||||
use League\OAuth2\Server\Entities\AccessTokenEntityInterface;
|
||||
use League\OAuth2\Server\Entities\RefreshTokenEntityInterface;
|
||||
use League\OAuth2\Server\Grant\RefreshTokenGrant;
|
||||
use League\OAuth2\Server\Repositories\AccessTokenRepositoryInterface;
|
||||
use League\OAuth2\Server\Repositories\ClientRepositoryInterface;
|
||||
use League\OAuth2\Server\Repositories\RefreshTokenRepositoryInterface;
|
||||
use League\OAuth2\Server\Repositories\ScopeRepositoryInterface;
|
||||
use LeagueTests\Stubs\AccessTokenEntity;
|
||||
use LeagueTests\Stubs\ClientEntity;
|
||||
use LeagueTests\Stubs\CryptTraitStub;
|
||||
use LeagueTests\Stubs\RefreshTokenEntity;
|
||||
use LeagueTests\Stubs\ScopeEntity;
|
||||
use LeagueTests\Stubs\StubResponseType;
|
||||
use Zend\Diactoros\ServerRequest;
|
||||
@@ -29,7 +32,7 @@ class RefreshTokenGrantTest extends \PHPUnit_Framework_TestCase
|
||||
|
||||
public function testGetIdentifier()
|
||||
{
|
||||
$refreshTokenRepositoryMock = $this->getMock(RefreshTokenRepositoryInterface::class);
|
||||
$refreshTokenRepositoryMock = $this->getMockBuilder(RefreshTokenRepositoryInterface::class)->getMock();
|
||||
|
||||
$grant = new RefreshTokenGrant($refreshTokenRepositoryMock);
|
||||
$this->assertEquals('refresh_token', $grant->getIdentifier());
|
||||
@@ -39,7 +42,6 @@ class RefreshTokenGrantTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
$client = new ClientEntity();
|
||||
$client->setIdentifier('foo');
|
||||
$client->setSecret('bar');
|
||||
$clientRepositoryMock = $this->getMockBuilder(ClientRepositoryInterface::class)->getMock();
|
||||
$clientRepositoryMock->method('getClientEntity')->willReturn($client);
|
||||
|
||||
@@ -48,11 +50,13 @@ class RefreshTokenGrantTest extends \PHPUnit_Framework_TestCase
|
||||
$scopeRepositoryMock->method('getScopeEntityByIdentifier')->willReturn($scopeEntity);
|
||||
|
||||
$accessTokenRepositoryMock = $this->getMockBuilder(AccessTokenRepositoryInterface::class)->getMock();
|
||||
$accessTokenRepositoryMock->method('getNewToken')->willReturn(new AccessTokenEntity());
|
||||
$accessTokenRepositoryMock
|
||||
->expects($this->once())
|
||||
->method('persistNewAccessToken')->willReturnSelf();
|
||||
|
||||
$refreshTokenRepositoryMock = $this->getMockBuilder(RefreshTokenRepositoryInterface::class)->getMock();
|
||||
$refreshTokenRepositoryMock->method('getNewRefreshToken')->willReturn(new RefreshTokenEntity());
|
||||
$refreshTokenRepositoryMock
|
||||
->expects($this->once())
|
||||
->method('persistNewRefreshToken')->willReturnSelf();
|
||||
@@ -61,8 +65,8 @@ class RefreshTokenGrantTest extends \PHPUnit_Framework_TestCase
|
||||
$grant->setClientRepository($clientRepositoryMock);
|
||||
$grant->setScopeRepository($scopeRepositoryMock);
|
||||
$grant->setAccessTokenRepository($accessTokenRepositoryMock);
|
||||
$grant->setPublicKeyPath('file://' . __DIR__ . '/../Stubs/public.key');
|
||||
$grant->setPrivateKeyPath('file://' . __DIR__ . '/../Stubs/private.key');
|
||||
$grant->setPublicKey(new CryptKey('file://' . __DIR__ . '/../Stubs/public.key'));
|
||||
$grant->setPrivateKey(new CryptKey('file://' . __DIR__ . '/../Stubs/private.key'));
|
||||
|
||||
$oldRefreshToken = $this->cryptStub->doEncrypt(
|
||||
json_encode(
|
||||
@@ -87,7 +91,7 @@ class RefreshTokenGrantTest extends \PHPUnit_Framework_TestCase
|
||||
);
|
||||
|
||||
$responseType = new StubResponseType();
|
||||
$grant->respondToRequest($serverRequest, $responseType, new \DateInterval('PT5M'));
|
||||
$grant->respondToAccessTokenRequest($serverRequest, $responseType, new \DateInterval('PT5M'));
|
||||
|
||||
$this->assertTrue($responseType->getAccessToken() instanceof AccessTokenEntityInterface);
|
||||
$this->assertTrue($responseType->getRefreshToken() instanceof RefreshTokenEntityInterface);
|
||||
@@ -97,15 +101,16 @@ class RefreshTokenGrantTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
$client = new ClientEntity();
|
||||
$client->setIdentifier('foo');
|
||||
$client->setSecret('bar');
|
||||
$clientRepositoryMock = $this->getMockBuilder(ClientRepositoryInterface::class)->getMock();
|
||||
$clientRepositoryMock->method('getClientEntity')->willReturn($client);
|
||||
|
||||
$accessTokenRepositoryMock = $this->getMockBuilder(AccessTokenRepositoryInterface::class)->getMock();
|
||||
$accessTokenRepositoryMock->method('getNewToken')->willReturn(new AccessTokenEntity());
|
||||
$accessTokenRepositoryMock->method('persistNewAccessToken')->willReturnSelf();
|
||||
|
||||
$refreshTokenRepositoryMock = $this->getMockBuilder(RefreshTokenRepositoryInterface::class)->getMock();
|
||||
$refreshTokenRepositoryMock->method('persistNewRefreshToken')->willReturnSelf();
|
||||
$refreshTokenRepositoryMock->method('getNewRefreshToken')->willReturn(new RefreshTokenEntity());
|
||||
|
||||
$scope = new ScopeEntity();
|
||||
$scope->setIdentifier('foo');
|
||||
@@ -116,8 +121,8 @@ class RefreshTokenGrantTest extends \PHPUnit_Framework_TestCase
|
||||
$grant->setClientRepository($clientRepositoryMock);
|
||||
$grant->setAccessTokenRepository($accessTokenRepositoryMock);
|
||||
$grant->setScopeRepository($scopeRepositoryMock);
|
||||
$grant->setPublicKeyPath('file://' . __DIR__ . '/../Stubs/public.key');
|
||||
$grant->setPrivateKeyPath('file://' . __DIR__ . '/../Stubs/private.key');
|
||||
$grant->setPublicKey(new CryptKey('file://' . __DIR__ . '/../Stubs/public.key'));
|
||||
$grant->setPrivateKey(new CryptKey('file://' . __DIR__ . '/../Stubs/private.key'));
|
||||
|
||||
$oldRefreshToken = $this->cryptStub->doEncrypt(
|
||||
json_encode(
|
||||
@@ -143,7 +148,7 @@ class RefreshTokenGrantTest extends \PHPUnit_Framework_TestCase
|
||||
);
|
||||
|
||||
$responseType = new StubResponseType();
|
||||
$grant->respondToRequest($serverRequest, $responseType, new \DateInterval('PT5M'));
|
||||
$grant->respondToAccessTokenRequest($serverRequest, $responseType, new \DateInterval('PT5M'));
|
||||
|
||||
$this->assertTrue($responseType->getAccessToken() instanceof AccessTokenEntityInterface);
|
||||
$this->assertTrue($responseType->getRefreshToken() instanceof RefreshTokenEntityInterface);
|
||||
@@ -157,7 +162,6 @@ class RefreshTokenGrantTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
$client = new ClientEntity();
|
||||
$client->setIdentifier('foo');
|
||||
$client->setSecret('bar');
|
||||
$clientRepositoryMock = $this->getMockBuilder(ClientRepositoryInterface::class)->getMock();
|
||||
$clientRepositoryMock->method('getClientEntity')->willReturn($client);
|
||||
|
||||
@@ -176,8 +180,8 @@ class RefreshTokenGrantTest extends \PHPUnit_Framework_TestCase
|
||||
$grant->setClientRepository($clientRepositoryMock);
|
||||
$grant->setAccessTokenRepository($accessTokenRepositoryMock);
|
||||
$grant->setScopeRepository($scopeRepositoryMock);
|
||||
$grant->setPublicKeyPath('file://' . __DIR__ . '/../Stubs/public.key');
|
||||
$grant->setPrivateKeyPath('file://' . __DIR__ . '/../Stubs/private.key');
|
||||
$grant->setPublicKey(new CryptKey('file://' . __DIR__ . '/../Stubs/public.key'));
|
||||
$grant->setPrivateKey(new CryptKey('file://' . __DIR__ . '/../Stubs/private.key'));
|
||||
|
||||
$oldRefreshToken = $this->cryptStub->doEncrypt(
|
||||
json_encode(
|
||||
@@ -203,7 +207,7 @@ class RefreshTokenGrantTest extends \PHPUnit_Framework_TestCase
|
||||
);
|
||||
|
||||
$responseType = new StubResponseType();
|
||||
$grant->respondToRequest($serverRequest, $responseType, new \DateInterval('PT5M'));
|
||||
$grant->respondToAccessTokenRequest($serverRequest, $responseType, new \DateInterval('PT5M'));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -214,7 +218,6 @@ class RefreshTokenGrantTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
$client = new ClientEntity();
|
||||
$client->setIdentifier('foo');
|
||||
$client->setSecret('bar');
|
||||
$clientRepositoryMock = $this->getMockBuilder(ClientRepositoryInterface::class)->getMock();
|
||||
$clientRepositoryMock->method('getClientEntity')->willReturn($client);
|
||||
|
||||
@@ -224,8 +227,8 @@ class RefreshTokenGrantTest extends \PHPUnit_Framework_TestCase
|
||||
$grant = new RefreshTokenGrant($refreshTokenRepositoryMock);
|
||||
$grant->setClientRepository($clientRepositoryMock);
|
||||
$grant->setAccessTokenRepository($accessTokenRepositoryMock);
|
||||
$grant->setPublicKeyPath('file://' . __DIR__ . '/../Stubs/public.key');
|
||||
$grant->setPrivateKeyPath('file://' . __DIR__ . '/../Stubs/private.key');
|
||||
$grant->setPublicKey(new CryptKey('file://' . __DIR__ . '/../Stubs/public.key'));
|
||||
$grant->setPrivateKey(new CryptKey('file://' . __DIR__ . '/../Stubs/private.key'));
|
||||
|
||||
$serverRequest = new ServerRequest();
|
||||
$serverRequest = $serverRequest->withParsedBody(
|
||||
@@ -236,7 +239,7 @@ class RefreshTokenGrantTest extends \PHPUnit_Framework_TestCase
|
||||
);
|
||||
|
||||
$responseType = new StubResponseType();
|
||||
$grant->respondToRequest($serverRequest, $responseType, new \DateInterval('PT5M'));
|
||||
$grant->respondToAccessTokenRequest($serverRequest, $responseType, new \DateInterval('PT5M'));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -247,7 +250,6 @@ class RefreshTokenGrantTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
$client = new ClientEntity();
|
||||
$client->setIdentifier('foo');
|
||||
$client->setSecret('bar');
|
||||
$clientRepositoryMock = $this->getMockBuilder(ClientRepositoryInterface::class)->getMock();
|
||||
$clientRepositoryMock->method('getClientEntity')->willReturn($client);
|
||||
|
||||
@@ -257,8 +259,8 @@ class RefreshTokenGrantTest extends \PHPUnit_Framework_TestCase
|
||||
$grant = new RefreshTokenGrant($refreshTokenRepositoryMock);
|
||||
$grant->setClientRepository($clientRepositoryMock);
|
||||
$grant->setAccessTokenRepository($accessTokenRepositoryMock);
|
||||
$grant->setPublicKeyPath('file://' . __DIR__ . '/../Stubs/public.key');
|
||||
$grant->setPrivateKeyPath('file://' . __DIR__ . '/../Stubs/private.key');
|
||||
$grant->setPublicKey(new CryptKey('file://' . __DIR__ . '/../Stubs/public.key'));
|
||||
$grant->setPrivateKey(new CryptKey('file://' . __DIR__ . '/../Stubs/private.key'));
|
||||
|
||||
$oldRefreshToken = 'foobar';
|
||||
|
||||
@@ -272,7 +274,7 @@ class RefreshTokenGrantTest extends \PHPUnit_Framework_TestCase
|
||||
);
|
||||
|
||||
$responseType = new StubResponseType();
|
||||
$grant->respondToRequest($serverRequest, $responseType, new \DateInterval('PT5M'));
|
||||
$grant->respondToAccessTokenRequest($serverRequest, $responseType, new \DateInterval('PT5M'));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -283,7 +285,6 @@ class RefreshTokenGrantTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
$client = new ClientEntity();
|
||||
$client->setIdentifier('foo');
|
||||
$client->setSecret('bar');
|
||||
$clientRepositoryMock = $this->getMockBuilder(ClientRepositoryInterface::class)->getMock();
|
||||
$clientRepositoryMock->method('getClientEntity')->willReturn($client);
|
||||
|
||||
@@ -297,8 +298,8 @@ class RefreshTokenGrantTest extends \PHPUnit_Framework_TestCase
|
||||
$grant = new RefreshTokenGrant($refreshTokenRepositoryMock);
|
||||
$grant->setClientRepository($clientRepositoryMock);
|
||||
$grant->setAccessTokenRepository($accessTokenRepositoryMock);
|
||||
$grant->setPublicKeyPath('file://' . __DIR__ . '/../Stubs/public.key');
|
||||
$grant->setPrivateKeyPath('file://' . __DIR__ . '/../Stubs/private.key');
|
||||
$grant->setPublicKey(new CryptKey('file://' . __DIR__ . '/../Stubs/public.key'));
|
||||
$grant->setPrivateKey(new CryptKey('file://' . __DIR__ . '/../Stubs/private.key'));
|
||||
|
||||
$oldRefreshToken = $this->cryptStub->doEncrypt(
|
||||
json_encode(
|
||||
@@ -323,7 +324,7 @@ class RefreshTokenGrantTest extends \PHPUnit_Framework_TestCase
|
||||
);
|
||||
|
||||
$responseType = new StubResponseType();
|
||||
$grant->respondToRequest($serverRequest, $responseType, new \DateInterval('PT5M'));
|
||||
$grant->respondToAccessTokenRequest($serverRequest, $responseType, new \DateInterval('PT5M'));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -334,7 +335,6 @@ class RefreshTokenGrantTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
$client = new ClientEntity();
|
||||
$client->setIdentifier('foo');
|
||||
$client->setSecret('bar');
|
||||
$clientRepositoryMock = $this->getMockBuilder(ClientRepositoryInterface::class)->getMock();
|
||||
$clientRepositoryMock->method('getClientEntity')->willReturn($client);
|
||||
|
||||
@@ -344,8 +344,8 @@ class RefreshTokenGrantTest extends \PHPUnit_Framework_TestCase
|
||||
$grant = new RefreshTokenGrant($refreshTokenRepositoryMock);
|
||||
$grant->setClientRepository($clientRepositoryMock);
|
||||
$grant->setAccessTokenRepository($accessTokenRepositoryMock);
|
||||
$grant->setPublicKeyPath('file://' . __DIR__ . '/../Stubs/public.key');
|
||||
$grant->setPrivateKeyPath('file://' . __DIR__ . '/../Stubs/private.key');
|
||||
$grant->setPublicKey(new CryptKey('file://' . __DIR__ . '/../Stubs/public.key'));
|
||||
$grant->setPrivateKey(new CryptKey('file://' . __DIR__ . '/../Stubs/private.key'));
|
||||
|
||||
$oldRefreshToken = $this->cryptStub->doEncrypt(
|
||||
json_encode(
|
||||
@@ -370,7 +370,7 @@ class RefreshTokenGrantTest extends \PHPUnit_Framework_TestCase
|
||||
);
|
||||
|
||||
$responseType = new StubResponseType();
|
||||
$grant->respondToRequest($serverRequest, $responseType, new \DateInterval('PT5M'));
|
||||
$grant->respondToAccessTokenRequest($serverRequest, $responseType, new \DateInterval('PT5M'));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -381,7 +381,6 @@ class RefreshTokenGrantTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
$client = new ClientEntity();
|
||||
$client->setIdentifier('foo');
|
||||
$client->setSecret('bar');
|
||||
$clientRepositoryMock = $this->getMockBuilder(ClientRepositoryInterface::class)->getMock();
|
||||
$clientRepositoryMock->method('getClientEntity')->willReturn($client);
|
||||
|
||||
@@ -392,8 +391,8 @@ class RefreshTokenGrantTest extends \PHPUnit_Framework_TestCase
|
||||
$grant = new RefreshTokenGrant($refreshTokenRepositoryMock);
|
||||
$grant->setClientRepository($clientRepositoryMock);
|
||||
$grant->setAccessTokenRepository($accessTokenRepositoryMock);
|
||||
$grant->setPublicKeyPath('file://' . __DIR__ . '/../Stubs/public.key');
|
||||
$grant->setPrivateKeyPath('file://' . __DIR__ . '/../Stubs/private.key');
|
||||
$grant->setPublicKey(new CryptKey('file://' . __DIR__ . '/../Stubs/public.key'));
|
||||
$grant->setPrivateKey(new CryptKey('file://' . __DIR__ . '/../Stubs/private.key'));
|
||||
|
||||
$oldRefreshToken = $this->cryptStub->doEncrypt(
|
||||
json_encode(
|
||||
@@ -418,6 +417,6 @@ class RefreshTokenGrantTest extends \PHPUnit_Framework_TestCase
|
||||
);
|
||||
|
||||
$responseType = new StubResponseType();
|
||||
$grant->respondToRequest($serverRequest, $responseType, new \DateInterval('PT5M'));
|
||||
$grant->respondToAccessTokenRequest($serverRequest, $responseType, new \DateInterval('PT5M'));
|
||||
}
|
||||
}
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user