mirror of
https://github.com/elyby/oauth2-server.git
synced 2025-05-31 14:12:07 +05:30
Compare commits
1230 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
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 | ||
|
9533595394 | ||
|
5b977b1495 | ||
|
1de13cf892 | ||
|
1c47ec51f8 | ||
|
fbf4388b01 | ||
|
a867fdd891 | ||
|
1041a39d08 | ||
|
e23570535f | ||
|
b1cf6a8436 | ||
|
d8e1e0e00e | ||
|
fe0ed765a5 | ||
|
7ce31bda87 | ||
|
630a92b45f | ||
|
2b76e2bf6e | ||
|
115237bc1a | ||
|
6383a58755 | ||
|
614fbde56e | ||
|
0fbe109e20 | ||
|
57216984e9 | ||
|
267bd3c5d4 | ||
|
a18b8c57b2 | ||
|
cca401e66e | ||
|
55ff59edf4 | ||
|
a49c762683 | ||
|
b5b5d9f347 | ||
|
07b2758cba | ||
|
864a27f2c8 | ||
|
a698a4da7e | ||
|
1ad44d1ce0 | ||
|
b480373249 | ||
|
95cdaae17f | ||
|
61986db5ee | ||
|
878afeb9f9 | ||
|
e9dd1478c4 | ||
|
945731cb39 | ||
|
f688401f63 | ||
|
09770dc537 | ||
|
dcf3f50b87 | ||
|
59e8785f50 | ||
|
ca54a387c8 | ||
|
6fea054381 | ||
|
ed17b6540e | ||
|
e27b13ee7d | ||
|
67f835a606 | ||
|
8685006743 | ||
|
400eae153b | ||
|
c880d5c1ec | ||
|
9ee2e7271f | ||
|
b629b5e53f | ||
|
4b775fe241 | ||
|
8196f5c832 | ||
|
890fdeba16 | ||
|
c2e83ff359 | ||
|
51a1a75d37 | ||
|
251190d828 | ||
|
a350705a01 | ||
|
7293ff9e9d | ||
|
c207addf87 | ||
|
3af75729b8 | ||
|
7b8d9c9af3 | ||
|
15b6506644 | ||
|
bd12c8b1a9 | ||
|
c3c49c83f9 | ||
|
2f459b6470 | ||
|
ee91072455 | ||
|
25f93071ea | ||
|
079ed0040a | ||
|
5bbf703711 | ||
|
d635b3484b | ||
|
3365f3d733 | ||
|
9e828f8f3c | ||
|
c7a5a57304 | ||
|
ae0edc40aa | ||
|
264bc7b625 | ||
|
7159352108 | ||
|
a70bc2360a | ||
|
472ec68bbe | ||
|
e946c1e106 | ||
|
4c392db673 | ||
|
66e473b1f0 | ||
|
91c8daeb99 | ||
|
9ffe806112 | ||
|
9e04da01de | ||
|
592f60de70 | ||
|
5ae9827d67 | ||
|
5e8d2fe0f5 | ||
|
9b665f494f | ||
|
ced63e2051 | ||
|
c3ffed2daf | ||
|
ecad2b98ae | ||
|
a0402f1994 | ||
|
6e74de50e5 | ||
|
4ab9c52767 | ||
|
2b2d4a3df7 | ||
|
0ae8863322 | ||
|
4c55b6879d | ||
|
9590550799 | ||
|
c40a10a071 | ||
|
f7f3cdee24 | ||
|
edf0ee8622 | ||
|
c490cd4ef2 | ||
|
a716a08be6 | ||
|
3b4a8cf5f3 | ||
|
8f0cb0e78c | ||
|
fb1fa71b5d | ||
|
0216638903 | ||
|
5074ad9a6c | ||
|
721a31534e | ||
|
01517bb57a | ||
|
0f2c6e7f4e | ||
|
320d9e65d5 | ||
|
1218cede79 | ||
|
8ff0cb6495 | ||
|
1bdeb71efb | ||
|
1632b80631 | ||
|
5760450854 | ||
|
9c66688d19 | ||
|
da53067e63 | ||
|
84172c0d29 | ||
|
997d390f3d | ||
|
e2794c47af | ||
|
0d0aaa8764 | ||
|
ad270f7d9d | ||
|
a1bdaae9a9 | ||
|
e08669d50c | ||
|
d02437dd73 | ||
|
cee4147688 | ||
|
eedcfe115c | ||
|
f06adb38cd | ||
|
9675dff220 | ||
|
2488cbd55d | ||
|
27d4441d1d | ||
|
bc82f5badd | ||
|
7f539f8736 | ||
|
a4b65241ad | ||
|
8b601d79b9 | ||
|
d0878300d0 | ||
|
97c138bb0b | ||
|
937d425e4c | ||
|
ff5ea52ccd | ||
|
a2460886f6 | ||
|
65bcc97fc3 | ||
|
60c45ab8fe | ||
|
a644eacea7 | ||
|
13baa0bb26 | ||
|
e8a01c3bcd | ||
|
064eb85f4e | ||
|
ad5b242d10 | ||
|
704e114568 | ||
|
73cd377c4b | ||
|
3b36ae9000 | ||
|
7f67000d53 | ||
|
de000b72a4 | ||
|
e808528cc8 | ||
|
fb77a78fb3 | ||
|
0d8cb0d06f | ||
|
fc53d636f5 | ||
|
dbcaaa1f35 | ||
|
5d6634aa9f | ||
|
099c9ce41b | ||
|
186853390a | ||
|
335630f150 | ||
|
de13e14cdd | ||
|
2bd45f2a6b | ||
|
e20c529f39 | ||
|
08ad67e401 | ||
|
7f2fd69d0a | ||
|
29068dd84c | ||
|
174ae490fc | ||
|
fa3fb36ed8 | ||
|
21e2ccd0fb | ||
|
aa0570c932 | ||
|
9a8b7ec898 | ||
|
1f6bb40952 | ||
|
2f914a0aa3 | ||
|
95e3c1d1a2 | ||
|
64d4c4a38a | ||
|
655f6b9771 | ||
|
d95958bae4 | ||
|
85b9412813 | ||
|
1a5030200a | ||
|
796106b6c1 | ||
|
4234b69f3a | ||
|
6dd4caf056 | ||
|
f6cc8bbb42 | ||
|
0115c41eea | ||
|
f314154216 | ||
|
9b97778618 | ||
|
5e326d9e45 | ||
|
d2760e4ec7 | ||
|
2025749fa4 | ||
|
1c913fe75e | ||
|
556c9fa782 | ||
|
c5bc63027f | ||
|
ac9955b393 | ||
|
fccb06ed67 | ||
|
f29703ea24 | ||
|
dcc3f5d856 | ||
|
264eba9f20 | ||
|
c2c199cf98 | ||
|
0b6bcad9fb | ||
|
38a7e53cb5 | ||
|
f4b83baf74 | ||
|
5a08a0cbe2 | ||
|
7a628409db | ||
|
c6d806d3f7 | ||
|
bfcf7af4d8 | ||
|
d96f57d27f | ||
|
95919a688e | ||
|
8b185e0580 | ||
|
ca776e83a2 | ||
|
ddf3f1b890 | ||
|
a40ac5d77b | ||
|
4bc89f3fc2 | ||
|
11d25eb5a1 | ||
|
770bda8f10 | ||
|
7a8c92b3d9 | ||
|
96620c8b3b | ||
|
92a101f263 | ||
|
b85f81c429 | ||
|
8fb64041df | ||
|
3ad97b4ef4 | ||
|
44155a8efc | ||
|
b7b1f56d0c | ||
|
3e5889e93b | ||
|
ef5904ab1a | ||
|
94cc7c2bc7 | ||
|
0490736861 | ||
|
1e1043c04f | ||
|
8591fc7686 | ||
|
86b75edca0 | ||
|
13ddec3283 | ||
|
322caa77af | ||
|
95634fb390 | ||
|
6beb8d42ff | ||
|
6cffbfe33b | ||
|
5fcb47d66a | ||
|
abaf399f5f | ||
|
cbd45cc5ab | ||
|
8566a128c8 | ||
|
419cb6d149 | ||
|
f1d06e7c33 | ||
|
212938d1e2 | ||
|
cd19f11799 | ||
|
55c8df8312 | ||
|
4862ca7d60 | ||
|
660378c7b3 | ||
|
06ee612bb1 | ||
|
3c4347e385 | ||
|
168e7640c6 | ||
|
3d08051cbb | ||
|
0486d93fa3 | ||
|
5a8659471c | ||
|
f6664c6917 | ||
|
5f22ead287 | ||
|
19b12cda8e | ||
|
6c787c374c | ||
|
cd68103267 | ||
|
6332ecfa0b | ||
|
e43d95415b | ||
|
d755a8c01d | ||
|
c7a904ca40 | ||
|
8ee4dc7eb9 | ||
|
645f719ee9 | ||
|
0cc13630cc | ||
|
e21a13c82c | ||
|
a4ce1e510e | ||
|
ad05a5cae6 | ||
|
e6cc6c35ec | ||
|
f74bca33ab | ||
|
90d9d7bdd6 | ||
|
8d8dbaea0c | ||
|
03391e9630 | ||
|
7242a8db31 | ||
|
f44b618531 | ||
|
9e4fd82763 | ||
|
0744d8e926 | ||
|
3efe7b3c0a | ||
|
44ff8692dc | ||
|
6108c06e34 | ||
|
dce1620f60 | ||
|
bcd84320da | ||
|
a40374e6ec | ||
|
748ae15376 | ||
|
7811721d28 | ||
|
c5e5ae5555 | ||
|
8f724bb720 | ||
|
e9f8e7ac19 | ||
|
c4830608a2 | ||
|
65d981ad32 | ||
|
3de1b5917a | ||
|
0fbe447862 | ||
|
84a9802a67 | ||
|
f7b3c018c5 | ||
|
a88c30cb53 | ||
|
5e6f0fc6a3 | ||
|
b57b497cb7 | ||
|
0b061e3086 | ||
|
304ea2baf4 | ||
|
56060b2c16 | ||
|
633746b02e | ||
|
94b221c8a1 | ||
|
20ad5d251c | ||
|
e95a228128 | ||
|
dc2919710c | ||
|
936b8f93ec | ||
|
c1d15aa15c | ||
|
70e9d7b699 | ||
|
79791e5848 | ||
|
0efa7cd7ea | ||
|
eef5cf39d4 | ||
|
6fb3fb5110 | ||
|
a2bbb17483 | ||
|
3135f1796e | ||
|
d565665ccb | ||
|
13a1ea6db8 | ||
|
6358be90c2 | ||
|
de89a6bc89 | ||
|
e03ad0d52f | ||
|
2a20de991b | ||
|
b8732a2f83 | ||
|
1bdad3ad14 | ||
|
fd47712060 | ||
|
6339524c86 | ||
|
5f9feda80c | ||
|
9958e1bf80 | ||
|
758471ec16 | ||
|
3fcba9339d | ||
|
f9c0cb08e0 | ||
|
a9313e76d4 | ||
|
59080a8319 | ||
|
524f04c78c | ||
|
8e04868320 | ||
|
c5db707e69 | ||
|
fa3dc4e055 | ||
|
f9b2441c41 | ||
|
09f1d0fbb1 | ||
|
ed7f78179a | ||
|
6e92239dd7 | ||
|
5ab91d7345 | ||
|
6c054dbf35 | ||
|
530cdb02f0 | ||
|
0a2d4c1649 | ||
|
bb17abfe26 | ||
|
e7e4892408 | ||
|
46648f3e80 | ||
|
6f2e2a0071 | ||
|
b7ba593856 | ||
|
c0bdd22154 | ||
|
f5d731def9 | ||
|
32b451aa21 | ||
|
96a0c34d41 | ||
|
b95780022a | ||
|
c0823c464e | ||
|
cc43a31ca6 | ||
|
da8efa20cd | ||
|
03e4ac7ea6 | ||
|
1442842da9 | ||
|
0a602cb022 | ||
|
b479cb7912 | ||
|
41c7a6e731 | ||
|
82413513e8 | ||
|
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 | ||
|
18b104d0ac | ||
|
2e3c6b4f3a | ||
|
8e9b12fefd | ||
|
95a2308ff6 | ||
|
9985f3eee2 | ||
|
39df4ff9b1 | ||
|
90d18c553d | ||
|
385b03db6f | ||
|
a15995c126 | ||
|
f4cfd37745 | ||
|
a0d5d5817b | ||
|
d468cbf600 | ||
|
be14b3a2df | ||
|
1f1f0d8f15 | ||
|
8fcf93c489 | ||
|
bdd71743cd | ||
|
77b5282b46 | ||
|
e88d802918 | ||
|
61ab070692 | ||
|
d3ed454881 | ||
|
b5bbf8332f | ||
|
110d5ce76f | ||
|
bf1c46d62f | ||
|
5840ace38f | ||
|
eabcf82268 | ||
|
6a78d53d03 | ||
|
b831d19f8d | ||
|
721e52c5d9 | ||
|
6e73099d8c | ||
|
784af67367 | ||
|
4f053bb63a | ||
|
5211d1902c | ||
|
ffc8823e4f | ||
|
f912f60a59 | ||
|
476b8d81c1 | ||
|
2b2067e162 | ||
|
9048617e35 | ||
|
775d42115a | ||
|
f3705865a3 | ||
|
15cef6ba16 | ||
|
72b741d7c9 | ||
|
26c1abdd3c | ||
|
56f6df11a8 | ||
|
997d4f2eb7 | ||
|
d63efc8dbf | ||
|
7a3670523d | ||
|
1e39f1d84a | ||
|
0b66fd1948 | ||
|
164de644e9 | ||
|
f1da0d2943 | ||
|
f964fd2962 | ||
|
36a1a430b5 | ||
|
3721ecb40a | ||
|
5fcf01f4c8 | ||
|
a16a1dbb7d | ||
|
f357602090 | ||
|
a48630c837 | ||
|
171be1c422 | ||
|
324b6db5e6 | ||
|
a73322fb43 | ||
|
027971776b | ||
|
7c57310b67 | ||
|
810544ec0a | ||
|
34a6b66b8c | ||
|
61738a7fe2 | ||
|
51184259d1 | ||
|
b21de11429 | ||
|
cf6e86c9d4 | ||
|
f6fdbc7142 | ||
|
7f7f45662a | ||
|
5d7eeb0512 | ||
|
742b51c2cd | ||
|
f92a68cc72 | ||
|
295d8ffa24 | ||
|
3d08140651 | ||
|
cc7596f3b3 | ||
|
ec8a8393ee | ||
|
3869b8f406 | ||
|
7da7484008 | ||
|
b42ba4af17 | ||
|
dd795a82f4 | ||
|
166362d3cd | ||
|
d43391564c | ||
|
ea6edf572a | ||
|
19b64c2e65 | ||
|
612775466c | ||
|
740ea24e08 | ||
|
e1c14abf6c | ||
|
d1aae27359 | ||
|
80aeaf9200 | ||
|
282bb20cc8 | ||
|
b727be55a2 | ||
|
cf80a2d6ce | ||
|
72a5c1794a | ||
|
707c85b0d6 | ||
|
c56562b0b8 | ||
|
d0b2498b43 | ||
|
17be6f4549 | ||
|
b50fbff1e3 | ||
|
7375a348c6 | ||
|
ae5dd9ce65 | ||
|
f9e56ff62a | ||
|
1bcf7ee20f | ||
|
bee9c6a51d | ||
|
851c7c0eb1 | ||
|
7fff4a8fe8 | ||
|
44ac01ee0e | ||
|
60bd334b46 | ||
|
7398bee59e | ||
|
40420f27ed | ||
|
d32bfaa757 | ||
|
2653a174bb | ||
|
676fb4c06a | ||
|
7f815275d6 | ||
|
a056e2fe03 | ||
|
48d9fde133 | ||
|
a12786cbd5 | ||
|
164cc6ddb9 | ||
|
27f51d33e1 | ||
|
2108c88dfb | ||
|
a1726903b5 | ||
|
8075190e0c | ||
|
3b176fe220 | ||
|
986dc59627 | ||
|
0878897969 | ||
|
0ce7ecb45a | ||
|
7a63f42462 | ||
|
774341c346 | ||
|
c8983b35a0 | ||
|
edaccab04b | ||
|
f8b61b47b9 | ||
|
b8331d12e4 | ||
|
92404ab2bf | ||
|
3b17872f10 | ||
|
8cfa3dcdad | ||
|
9ec1380889 | ||
|
2af7195f06 | ||
|
8c6fd6c05a | ||
|
2df6446eb2 | ||
|
e1c0ff2685 | ||
|
6157bd77ca | ||
|
76de634f2b | ||
|
cfada388db | ||
|
2f971dc77f | ||
|
ae7b7e9aa9 | ||
|
bed6c3287e | ||
|
f83e5a8731 | ||
|
35369038db | ||
|
6a1f927a6c | ||
|
b2c0933ee6 | ||
|
3104d13eba | ||
|
8b1f3ef193 | ||
|
1ff885cff1 | ||
|
d950797bd9 | ||
|
d6e6b8b710 | ||
|
001c15bfad | ||
|
7fbc563524 | ||
|
0d949d53f3 | ||
|
d071cd112a | ||
|
4c1cd04a24 | ||
|
30162c8899 | ||
|
b21aac0ab2 | ||
|
73917a0327 | ||
|
ad86f71b34 | ||
|
d58877131d | ||
|
846b4d1652 | ||
|
583c21e7db | ||
|
7dc5a8090f | ||
|
6b29b7450e | ||
|
b9debaab26 | ||
|
856051bfb3 | ||
|
fa55a791e7 | ||
|
5c5d7d5340 | ||
|
a2a768b6e6 | ||
|
4bbbc72035 | ||
|
3815355489 | ||
|
9bb7af6f83 | ||
|
d16b1b72ba | ||
|
e37289231d | ||
|
1c2ec943e9 | ||
|
17dfc897b4 | ||
|
7586e62da1 | ||
|
a1c3746a5a | ||
|
d23dc4d247 | ||
|
293bc52972 | ||
|
11ab167376 | ||
|
f290de6dfc | ||
|
d260167155 | ||
|
3f114dc5e3 | ||
|
fedd10b5ed | ||
|
746cd4ab7d | ||
|
5848c0d920 | ||
|
db7c42cc91 | ||
|
f01cf7ef2f | ||
|
61f8195edd | ||
|
c38d20b163 | ||
|
fbf1535db1 | ||
|
90ce1932cc | ||
|
b60693c5d6 | ||
|
736a7b95eb | ||
|
b50f7ce04e | ||
|
b2514e35f4 | ||
|
bc314f7c52 | ||
|
72e3ddad1e | ||
|
6333a975f8 | ||
|
44ab7b6135 | ||
|
bfcccb2671 | ||
|
3183828c1c | ||
|
6be7c119db | ||
|
0f13ff188a | ||
|
099f009b39 | ||
|
136edf16c5 | ||
|
62d658524b | ||
|
5b9f9a500d | ||
|
05d33f7020 | ||
|
d9bf0e5899 | ||
|
63be2684d3 | ||
|
536ef3244d | ||
|
a3f5d20592 | ||
|
1e3a192920 | ||
|
b68a5c2abb | ||
|
643c3493c4 | ||
|
64ca2a4b49 | ||
|
1ff3d1adda | ||
|
9e2a6ed238 | ||
|
be51cdf9b1 | ||
|
13cd0cacdf | ||
|
67587e450b | ||
|
6ce190d33b | ||
|
f923e89c3d | ||
|
31c3cbe593 | ||
|
f03e4a9e37 | ||
|
7d8989a8cd | ||
|
b9e12a7fec | ||
|
d32cea1988 | ||
|
ce1a650ae1 | ||
|
01e823427f | ||
|
da92410ecb | ||
|
d65bd112a9 | ||
|
2ca3df60be | ||
|
23303905a8 | ||
|
0b8e69f0d0 | ||
|
a448f2167b | ||
|
3494b65be0 | ||
|
9ff841aa6f | ||
|
dc4136a6f5 | ||
|
7e4317cf54 | ||
|
522c7478c7 | ||
|
130d42c85e | ||
|
0433791bc6 | ||
|
79f15f3855 | ||
|
0754b9ec75 | ||
|
6568ca5790 | ||
|
30abfeefbf | ||
|
1483ce936b | ||
|
661086d3b8 | ||
|
ca1b977786 | ||
|
7525fc0884 | ||
|
06d5b343d6 | ||
|
07a42f6f43 | ||
|
8be92d413d | ||
|
71ac21b70e | ||
|
12ab753f15 | ||
|
684a8a269e | ||
|
cd60c2961f | ||
|
f046a024e4 | ||
|
90e585ba9a | ||
|
7e0e337134 | ||
|
324da27ea9 | ||
|
0a260f0c8c | ||
|
1a4cc3b750 | ||
|
b3da61822e | ||
|
69208fe0ac | ||
|
806838b8e4 | ||
|
2637af87ec | ||
|
ac3e787278 | ||
|
ffe59f5a5f | ||
|
7b9899c46b | ||
|
c29340ae27 | ||
|
ad12a088cf | ||
|
0810be9ce4 | ||
|
7f75246619 | ||
|
5ec1bf8a88 | ||
|
443d72ee24 | ||
|
861da5fee9 | ||
|
f3fc921212 | ||
|
54e6bbd4a6 | ||
|
0d6c4f65b9 | ||
|
cfd1c93a46 | ||
|
29b09227ac | ||
|
6cb5863b81 | ||
|
2f14f6b391 | ||
|
94369abd60 | ||
|
45edac4216 | ||
|
5bdfc9908a | ||
|
1890d71838 | ||
|
00d5fb5834 | ||
|
49b776c495 | ||
|
31e03c2d36 | ||
|
395ee3bf49 | ||
|
6f85bcbbf1 | ||
|
47a5c1ba08 | ||
|
d123ba095c | ||
|
bfad6c7e28 | ||
|
7067a35d3a | ||
|
f40ada9ac7 | ||
|
ca61d5d4e0 | ||
|
7771bc04ec | ||
|
20032f33a2 | ||
|
b694cca743 | ||
|
1e78f62823 | ||
|
c6bc1b0cfc | ||
|
48dea185d8 | ||
|
f34dd4a0cb | ||
|
4362f17fd6 | ||
|
6d81c1e57e | ||
|
1a88d3f4c5 | ||
|
0a3215be8e | ||
|
954f29f879 | ||
|
4480aa3456 | ||
|
44db2b295f | ||
|
33f4f5b7ab | ||
|
e61782975a | ||
|
d7c1c50269 | ||
|
f2b5967f10 | ||
|
92779ad078 | ||
|
83c7dea1cc | ||
|
4486b7120f | ||
|
687e794ce3 | ||
|
c7dfc42d57 | ||
|
33c68a2103 | ||
|
92639fbbd6 | ||
|
9af1d2a201 | ||
|
f24d1be3e9 | ||
|
80802e5df4 | ||
|
6aa52adb3e | ||
|
cd767c07fa | ||
|
0b1edadaa7 | ||
|
c1269a97d6 | ||
|
5e4cd98706 | ||
|
4ebf3f838f | ||
|
11c4c93398 | ||
|
cf32b5dd1b | ||
|
8e164f4b99 | ||
|
400d4d8f1e | ||
|
5ffbe6ac37 | ||
|
f7231b2c6a | ||
|
9a6ab4141f | ||
|
ad5cef3b7d | ||
|
cd44bf8f48 | ||
|
d065549e95 | ||
|
e43bdc837c | ||
|
45b971d286 | ||
|
4096c8cd20 | ||
|
66febb7744 | ||
|
d517b4c9e1 | ||
|
2412f1f826 | ||
|
c5aee31405 | ||
|
81e9e7364b | ||
|
11664e6d37 | ||
|
d40ee11ef5 | ||
|
b9cedc8b93 | ||
|
58adefa7d0 | ||
|
61f039366b | ||
|
6a0596f40b | ||
|
e32f153acf | ||
|
4823bfde8b | ||
|
7e0115f0ad | ||
|
49650d1ae9 | ||
|
aae99c2487 | ||
|
0d293e7c30 | ||
|
be4799edc9 | ||
|
7516606fd3 | ||
|
e4c43faa33 | ||
|
87fbcb19af | ||
|
6300cd5d72 | ||
|
0b047fd8e4 | ||
|
07c04d15d7 | ||
|
54c2c48704 | ||
|
95d068e818 | ||
|
c5ffd05eee | ||
|
b3c3676381 | ||
|
7356c5ad74 | ||
|
b8e2c5a3f8 | ||
|
f7e68d6e10 | ||
|
719b87a40c | ||
|
62f5766908 | ||
|
f46c1d2aa4 | ||
|
1f61f45f5f | ||
|
8e0b525ba2 | ||
|
19bd476395 | ||
|
7fada0964d | ||
|
b82551c97d | ||
|
5c8ed58c67 | ||
|
ed7f5370ca | ||
|
97e7a00bca | ||
|
193018aecf | ||
|
76289c68da | ||
|
9f6576c0fa | ||
|
107991b0a7 | ||
|
ffc25fb276 | ||
|
97fd115530 | ||
|
8fbbc7bd07 | ||
|
228144a701 | ||
|
184fac507b | ||
|
82c10c32fd | ||
|
782f43c73a | ||
|
6e5327a0e2 | ||
|
5206d77167 | ||
|
bdd2bc322c | ||
|
e5315dc016 | ||
|
8b4b884a03 | ||
|
f78caa24bb | ||
|
79b1e39798 | ||
|
797ed66eda | ||
|
16bdc36ccb | ||
|
b5f02d0739 | ||
|
1183fe80c6 | ||
|
9f1f0cc3bc | ||
|
6981ced972 | ||
|
019dfa8836 | ||
|
7f6ca35628 | ||
|
e1a7f576e4 | ||
|
6250daabd3 | ||
|
04277aeaa0 | ||
|
647de842ff | ||
|
ed10cbb4dc | ||
|
ba5f2840fb | ||
|
e8aeaf0777 | ||
|
fcc1388aeb | ||
|
d7ddfe6452 | ||
|
785d3bd21f | ||
|
5893ba4e8e | ||
|
b2c07aa68f | ||
|
ac29fc4a62 | ||
|
f78bb954d0 | ||
|
29b0389a75 | ||
|
2aa318cfd7 | ||
|
82f7c7abaf | ||
|
2d90540531 | ||
|
de681b1ebf | ||
|
b5217271b0 | ||
|
cc1e78e1ff | ||
|
b12a1d84df | ||
|
901aab9deb | ||
|
9ac56ad547 | ||
|
c60b29d201 | ||
|
2a524efff5 | ||
|
c8c69829f0 | ||
|
22794d49d1 | ||
|
4e37d9bb61 | ||
|
af06f9f3ea | ||
|
aef86227da | ||
|
54ffa58e7b | ||
|
5f7c14789b | ||
|
0bc16c04d9 | ||
|
8a2922697f | ||
|
1045c70bac | ||
|
3c9fd6be27 | ||
|
f83a9a7fa4 | ||
|
d10cc5040d | ||
|
d314c1efd9 | ||
|
468acbc369 | ||
|
013b1b53b4 | ||
|
5254c9d225 | ||
|
e07e0dba78 | ||
|
8556f616d3 | ||
|
064d4d967c | ||
|
a85feb1a32 | ||
|
8e7a975f1a | ||
|
5829781b38 | ||
|
895a379ed3 | ||
|
e4622b1f65 | ||
|
c5f48782e6 | ||
|
9de979a4ee | ||
|
20df1f50a6 | ||
|
40ea409aed | ||
|
a5b4198cb7 | ||
|
e71eb8074c | ||
|
0c4a45f329 | ||
|
115ca30f5a | ||
|
310c00a096 | ||
|
add1aa5949 | ||
|
36760a07cc | ||
|
11e0b004bd | ||
|
a2db7e1929 | ||
|
3cd5f50e64 | ||
|
603efeb80d | ||
|
69571bc8ef | ||
|
ca3b7d51df | ||
|
ac2beb08d6 | ||
|
0250d8d4d1 | ||
|
2d90a09f65 | ||
|
e9d867ba95 | ||
|
2c732a6647 | ||
|
0b1221ac14 | ||
|
ca4763483d | ||
|
9d6ecfae46 | ||
|
a3863fec2e | ||
|
5cd420bd5d | ||
|
e62bc4e98d | ||
|
7a38187076 | ||
|
40490db27f | ||
|
bc74aff46d | ||
|
337cb088e9 | ||
|
25332be3d1 | ||
|
13b15dfa3a | ||
|
7c1b913e49 | ||
|
9e5bd4cd67 | ||
|
427ae50704 | ||
|
449ba5005c | ||
|
b86d1f1406 | ||
|
f563a59ce8 | ||
|
324a3f0cdc | ||
|
f07d169336 | ||
|
227707c5dc | ||
|
6d7887dc36 | ||
|
5870368e33 | ||
|
9b9cf79f39 | ||
|
619d755008 | ||
|
2adefdf4c8 | ||
|
b5854215a7 | ||
|
302026d437 | ||
|
8d17049877 | ||
|
1f523c3a08 | ||
|
924066166c | ||
|
0dcda992c7 | ||
|
70aafb7521 | ||
|
f59213499c | ||
|
d9917a57e1 | ||
|
dba976d6ac | ||
|
8fe3ed7eb5 | ||
|
9099173db2 | ||
|
c6ac1de26b | ||
|
e55ca5bc05 | ||
|
4febb90210 | ||
|
75482c9e20 | ||
|
0db8850e81 | ||
|
9a224bd847 | ||
|
0c36045913 | ||
|
262ce23fb9 | ||
|
1419ba8cdc | ||
|
b55b73c1e8 | ||
|
e95ae977cc | ||
|
572e6935a6 | ||
|
dd88426323 | ||
|
14683bc65e | ||
|
1d3bc85423 | ||
|
10a4bf41ed | ||
|
041104e2b1 | ||
|
031cf3064a | ||
|
954ff19823 | ||
|
5bb1359ad7 | ||
|
2bd61f040b | ||
|
bacc9ce316 | ||
|
5ec2c24b5c | ||
|
ec9a08af63 | ||
|
6cade987a2 | ||
|
44408b873f | ||
|
b4bfa69c88 | ||
|
9c3c70a5fb | ||
|
556e9cc9ab | ||
|
d3158a830b | ||
|
4a71c376b8 | ||
|
ed427cba37 | ||
|
a358835522 | ||
|
23627c659e | ||
|
bee71c1e83 | ||
|
ad97273455 | ||
|
0b55dc4c01 | ||
|
4985770d07 | ||
|
a2bf4e0dfb | ||
|
cfbb037e07 | ||
|
6c28fea213 | ||
|
e5dc3001c4 | ||
|
69531c3eb5 | ||
|
89f3446b98 | ||
|
69710a5909 | ||
|
85353c5844 | ||
|
879d98abfb | ||
|
f612e105bd | ||
|
56f63bb4c0 | ||
|
8a42bc796f | ||
|
8fa7b303fa | ||
|
55b86e26ad | ||
|
e1f09db6af | ||
|
1e28faabb9 | ||
|
9a3a91760a | ||
|
78d65e102a | ||
|
701010b129 | ||
|
84afff9ad2 | ||
|
cfc61147e1 | ||
|
66ddba808f | ||
|
6324a97118 | ||
|
4170f4e841 | ||
|
5c21370691 | ||
|
c176c1cddc | ||
|
71b6f2c2bc | ||
|
f1567df802 | ||
|
307964d571 | ||
|
a1ca904255 | ||
|
6e045afa26 | ||
|
8f15158d1c | ||
|
ca4e749986 | ||
|
cc0ab4905a | ||
|
e5a48c929b | ||
|
829cef936a | ||
|
f78e05cb08 | ||
|
0999bf4de3 | ||
|
e442253e26 | ||
|
4c4155fdac | ||
|
d901e90602 | ||
|
32a7ed38a9 | ||
|
9dec6c4bfe | ||
|
bcfb9ec475 | ||
|
98be9ab252 | ||
|
e0f4ccb775 | ||
|
dca0898c2f | ||
|
7da9e1a9d7 | ||
|
a4a8f6e661 | ||
|
a9ecca92fc | ||
|
47c24e3181 | ||
|
4d36ebd3e7 | ||
|
0b3a9dc888 | ||
|
1fcdbf45b2 | ||
|
94a064e2f4 | ||
|
92b6ce3335 | ||
|
ee9549287e | ||
|
4b3e0bf668 | ||
|
05d4b68586 | ||
|
ec9c39c108 | ||
|
5d0b295a82 | ||
|
9ec5442f90 | ||
|
4112913813 | ||
|
5eb4227709 | ||
|
f5251a6080 | ||
|
86fb02d218 | ||
|
ef4a138237 | ||
|
d531a37412 | ||
|
ca599437f6 | ||
|
252afddbd3 | ||
|
c57c4b1b4f | ||
|
ba2dc90f3b | ||
|
7373f312da | ||
|
a01810d8fa | ||
|
3ea3eb5ebd | ||
|
11022e16ef | ||
|
8d06a7b685 | ||
|
c66c8092f9 | ||
|
591139f44d | ||
|
410ad09b5c | ||
|
51138f8738 | ||
|
aa8d38108f | ||
|
9372cc85d0 | ||
|
accb80289f | ||
|
e591fbb25c | ||
|
fdb89fb5e4 | ||
|
ce51821043 | ||
|
eac33d50b3 | ||
|
2552b73b17 | ||
|
8c4019693b | ||
|
b88ef82563 | ||
|
3e5b4a1735 | ||
|
41a7125370 | ||
|
c40484abb1 | ||
|
f4bcfee687 | ||
|
6d8eb9d05e | ||
|
76f2f6a5e1 | ||
|
d677b765b2 | ||
|
7035792325 | ||
|
351c2e97ea | ||
|
ddefb2ee16 | ||
|
c3b41a5e8a | ||
|
b16c58bfe1 | ||
|
e6d0a19e8f | ||
|
2296d09e92 | ||
|
69af252844 | ||
|
d9c598af3c | ||
|
3cb79fc2b5 | ||
|
39379fe5b6 | ||
|
1375f91e15 | ||
|
08a7055679 | ||
|
9f9a828294 | ||
|
77fbb2a851 | ||
|
c0683586e2 | ||
|
86a483f288 | ||
|
3617a3b37d | ||
|
24634aabd7 |
17
.gitattributes
vendored
17
.gitattributes
vendored
@@ -1,4 +1,13 @@
|
||||
tests/ export-ignore
|
||||
phpunit.xml export-ignore
|
||||
build.xml export-ignore
|
||||
test export-ignore
|
||||
* text=auto
|
||||
|
||||
/examples export-ignore
|
||||
/tests export-ignore
|
||||
/.gitattributes export-ignore
|
||||
/.gitignore export-ignore
|
||||
/.travis.yml export-ignore
|
||||
.travis.yml export-ignore
|
||||
.scrutinizer.yml export-ignore
|
||||
/phpunit.xml.dist export-ignore
|
||||
/CHANGELOG.md export-ignore
|
||||
/CONTRIBUTING.md export-ignore
|
||||
/README.md export-ignore
|
10
.gitignore
vendored
10
.gitignore
vendored
@@ -1,6 +1,8 @@
|
||||
/vendor
|
||||
/composer.lock
|
||||
/build/logs
|
||||
/build/coverage
|
||||
/docs
|
||||
/testing
|
||||
phpunit.xml
|
||||
.idea
|
||||
/examples/vendor
|
||||
examples/public.key
|
||||
examples/private.key
|
||||
build
|
||||
|
35
.scrutinizer.yml
Normal file
35
.scrutinizer.yml
Normal file
@@ -0,0 +1,35 @@
|
||||
filter:
|
||||
excluded_paths:
|
||||
- tests/*
|
||||
- vendor/*
|
||||
checks:
|
||||
php:
|
||||
code_rating: true
|
||||
remove_extra_empty_lines: true
|
||||
remove_php_closing_tag: true
|
||||
remove_trailing_whitespace: true
|
||||
fix_use_statements:
|
||||
remove_unused: true
|
||||
preserve_multiple: false
|
||||
preserve_blanklines: true
|
||||
order_alphabetically: true
|
||||
fix_php_opening_tag: true
|
||||
fix_linefeed: true
|
||||
fix_line_ending: true
|
||||
fix_identation_4spaces: true
|
||||
fix_doc_comments: true
|
||||
tools:
|
||||
external_code_coverage:
|
||||
timeout: 1800
|
||||
php_code_coverage: false
|
||||
php_code_sniffer:
|
||||
config:
|
||||
standard: PSR2
|
||||
filter:
|
||||
paths: ['src']
|
||||
php_loc:
|
||||
enabled: true
|
||||
excluded_dirs: [vendor, tests, examples]
|
||||
php_cpd:
|
||||
enabled: true
|
||||
excluded_dirs: [vendor, tests, examples]
|
53
.styleci.yml
Normal file
53
.styleci.yml
Normal file
@@ -0,0 +1,53 @@
|
||||
preset: psr2
|
||||
|
||||
enabled:
|
||||
- binary_operator_spaces
|
||||
- blank_line_before_return
|
||||
- concat_with_spaces
|
||||
- function_typehint_space
|
||||
- hash_to_slash_comment
|
||||
- include
|
||||
- lowercase_cast
|
||||
- method_separation
|
||||
- native_function_casing
|
||||
- no_blank_lines_after_class_opening
|
||||
- no_blank_lines_between_uses
|
||||
- no_duplicate_semicolons
|
||||
- no_leading_import_slash
|
||||
- no_leading_namespace_whitespace
|
||||
- no_multiline_whitespace_before_semicolons
|
||||
- no_php4_constructor
|
||||
- no_short_bool_cast
|
||||
- no_singleline_whitespace_before_semicolons
|
||||
- no_trailing_comma_in_singleline_array
|
||||
- no_unreachable_default_argument_value
|
||||
- no_unused_imports
|
||||
- no_whitespace_before_comma_in_array
|
||||
- ordered_imports
|
||||
- phpdoc_align
|
||||
- phpdoc_indent
|
||||
- phpdoc_inline_tag
|
||||
- phpdoc_no_access
|
||||
- phpdoc_no_simplified_null_return
|
||||
- phpdoc_order
|
||||
- phpdoc_property
|
||||
- phpdoc_scalar
|
||||
- phpdoc_separation
|
||||
- phpdoc_to_comment
|
||||
- phpdoc_trim
|
||||
- phpdoc_type_to_var
|
||||
- phpdoc_types
|
||||
- phpdoc_var_without_name
|
||||
- print_to_echo
|
||||
- short_array_syntax
|
||||
- short_scalar_cast
|
||||
- simplified_null_return
|
||||
- single_quote
|
||||
- spaces_cast
|
||||
- standardize_not_equal
|
||||
- ternary_operator_spaces
|
||||
- trailing_comma_in_multiline_array
|
||||
- trim_array_spaces
|
||||
- unary_operator_spaces
|
||||
- whitespace_after_comma_in_array
|
||||
- whitespacy_lines
|
26
.travis.yml
26
.travis.yml
@@ -1,8 +1,24 @@
|
||||
language: php
|
||||
|
||||
php:
|
||||
- 5.3
|
||||
- 5.4
|
||||
sudo: false
|
||||
|
||||
before_script: composer install --dev
|
||||
script: phpunit
|
||||
cache:
|
||||
directories:
|
||||
- vendor
|
||||
|
||||
php:
|
||||
- 5.5.9
|
||||
- 5.5
|
||||
- 5.6
|
||||
- 7.0
|
||||
- hhvm
|
||||
|
||||
install:
|
||||
- travis_retry composer install --no-interaction --prefer-source
|
||||
|
||||
script:
|
||||
- vendor/bin/phpunit
|
||||
|
||||
branches:
|
||||
only:
|
||||
- master
|
240
CHANGELOG.md
240
CHANGELOG.md
@@ -1,6 +1,242 @@
|
||||
# Changelog
|
||||
|
||||
## 2.0.0 (released 2013-05-06)
|
||||
## 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.
|
||||
|
||||
* JWT support
|
||||
* PSR-7 support
|
||||
* Improved exception errors
|
||||
* Replace all occurrences of the term "Storage" with "Repository"
|
||||
* Simplify repositories
|
||||
* Entities conform to interfaces and use traits
|
||||
* Auth code grant updated
|
||||
* Allow support for public clients
|
||||
* Add support for #439
|
||||
* Client credentials grant updated
|
||||
* Password grant updated
|
||||
* Allow support for public clients
|
||||
* Refresh token grant updated
|
||||
* Implement Implicit grant
|
||||
* Bearer token output type
|
||||
* Remove MAC token output type
|
||||
* Authorization server rewrite
|
||||
* Resource server class moved to PSR-7 middleware
|
||||
* Tests
|
||||
* Much much better documentation
|
||||
|
||||
## 4.1.5 (released 2016-01-04)
|
||||
|
||||
* Enable Symfony 3.0 support (#412)
|
||||
|
||||
## 4.1.4 (released 2015-11-13)
|
||||
|
||||
* Fix for determining access token in header (Issue #328)
|
||||
* Refresh tokens are now returned for MAC responses (Issue #356)
|
||||
* Added integration list to readme (Issue #341)
|
||||
* Expose parameter passed to exceptions (Issue #345)
|
||||
* Removed duplicate routing setup code (Issue #346)
|
||||
* Docs fix (Issues #347, #360, #380)
|
||||
* Examples fix (Issues #348, #358)
|
||||
* Fix typo in docblock (Issue #352)
|
||||
* Improved timeouts for MAC tokens (Issue #364)
|
||||
* `hash_hmac()` should output raw binary data, not hexits (Issue #370)
|
||||
* Improved regex for matching all Base64 characters (Issue #371)
|
||||
* Fix incorrect signature parameter (Issue #372)
|
||||
* AuthCodeGrant and RefreshTokenGrant don't require client_secret (Issue #377)
|
||||
* Added priority argument to event listener (Issue #388)
|
||||
|
||||
## 4.1.3 (released 2015-03-22)
|
||||
|
||||
* Docblock, namespace and inconsistency fixes (Issue #303)
|
||||
* Docblock type fix (Issue #310)
|
||||
* Example bug fix (Issue #300)
|
||||
* Updated league/event to ~2.1 (Issue #311)
|
||||
* Fixed missing session scope (Issue #319)
|
||||
* Updated interface docs (Issue #323)
|
||||
* `.travis.yml` updates
|
||||
|
||||
## 4.1.2 (released 2015-01-01)
|
||||
|
||||
* Remove side-effects in hash_equals() implementation (Issue #290)
|
||||
|
||||
## 4.1.1 (released 2014-12-31)
|
||||
|
||||
* Changed `symfony/http-foundation` dependency version to `~2.4` so package can be installed in Laravel `4.1.*`
|
||||
|
||||
## 4.1.0 (released 2014-12-27)
|
||||
|
||||
* Added MAC token support (Issue #158)
|
||||
* Fixed example init code (Issue #280)
|
||||
* Toggle refresh token rotation (Issue #286)
|
||||
* Docblock fixes
|
||||
|
||||
## 4.0.5 (released 2014-12-15)
|
||||
|
||||
* Prevent duplicate session in auth code grant (Issue #282)
|
||||
|
||||
## 4.0.4 (released 2014-12-03)
|
||||
|
||||
* Ensure refresh token hasn't expired (Issue #270)
|
||||
|
||||
## 4.0.3 (released 2014-12-02)
|
||||
|
||||
* Fix bad type hintings (Issue #267)
|
||||
* Do not forget to set the expire time (Issue #268)
|
||||
|
||||
## 4.0.2 (released 2014-11-21)
|
||||
|
||||
* Improved interfaces (Issue #255)
|
||||
* Learnt how to spell delimiter and so `getScopeDelimiter()` and `setScopeDelimiter()` methods have been renamed
|
||||
* Docblock improvements (Issue #254)
|
||||
|
||||
## 4.0.1 (released 2014-11-09)
|
||||
|
||||
* Alias the master branch in composer.json (Issue #243)
|
||||
* Numerous PHP CodeSniffer fixes (Issue #244)
|
||||
* .travis.yml update (Issue #245)
|
||||
* The getAccessToken method should return an AccessTokenEntity object instead of a string in ResourceServer.php (#246)
|
||||
|
||||
## 4.0.0 (released 2014-11-08)
|
||||
|
||||
* Complete rewrite
|
||||
* Check out the documentation - [http://oauth2.thephpleague.com](http://oauth2.thephpleague.com)
|
||||
|
||||
## 3.2.0 (released 2014-04-16)
|
||||
|
||||
* Added the ability to change the algorithm that is used to generate the token strings (Issue #151)
|
||||
|
||||
## 3.1.2 (released 2014-02-26)
|
||||
|
||||
* Support Authorization being an environment variable. [See more](http://fortrabbit.com/docs/essentials/quirks-and-constraints#authorization-header)
|
||||
|
||||
## 3.1.1 (released 2013-12-05)
|
||||
|
||||
* Normalize headers when `getallheaders()` is available (Issues #108 and #114)
|
||||
|
||||
## 3.1.0 (released 2013-12-05)
|
||||
|
||||
* No longer necessary to inject the authorisation server into a grant, the server will inject itself
|
||||
* Added test for 1419ba8cdcf18dd034c8db9f7de86a2594b68605
|
||||
|
||||
## 3.0.1 (released 2013-12-02)
|
||||
|
||||
* Forgot to tell TravisCI from testing PHP 5.3
|
||||
|
||||
## 3.0.0 (released 2013-12-02)
|
||||
|
||||
* Fixed spelling of Implicit grant class (Issue #84)
|
||||
* Travis CI now tests for PHP 5.5
|
||||
* Fixes for checking headers for resource server (Issues #79 and #)
|
||||
* The word "bearer" now has a capital "B" in JSON output to match OAuth 2.0 spec
|
||||
* All grants no longer remove old sessions by default
|
||||
* All grants now support custom access token TTL (Issue #92)
|
||||
* All methods which didn't before return a value now return `$this` to support method chaining
|
||||
* Removed the build in DB providers - these will be put in their own repos to remove baggage in the main repository
|
||||
* Removed support for PHP 5.3 because this library now uses traits and will use other modern PHP features going forward
|
||||
* Moved some grant related functions into a trait to reduce duplicate code
|
||||
|
||||
## 2.1.1 (released 2013-06-02)
|
||||
|
||||
* Added conditional `isValid()` flag to check for Authorization header only (thanks @alexmcroberts)
|
||||
* Fixed semantic meaning of `requireScopeParam()` and `requireStateParam()` by changing their default value to true
|
||||
* Updated some duff docblocks
|
||||
* Corrected array key call in Resource.php (Issue #63)
|
||||
|
||||
## 2.1 (released 2013-05-10)
|
||||
|
||||
* Moved zetacomponents/database to "suggest" in composer.json. If you rely on this feature you now need to include " zetacomponents/database" into "require" key in your own composer.json. (Issue #51)
|
||||
* New method in Refresh grant called `rotateRefreshTokens()`. Pass in `true` to issue a new refresh token each time an access token is refreshed. This parameter needs to be set to true in order to request reduced scopes with the new access token. (Issue #47)
|
||||
* Rename `key` column in oauth_scopes table to `scope` as `key` is a reserved SQL word. (Issue #45)
|
||||
* The `scope` parameter is no longer required by default as per the RFC. (Issue #43)
|
||||
* You can now set multiple default scopes by passing an array into `setDefaultScope()`. (Issue #42)
|
||||
* The password and client credentials grants now allow for multiple sessions per user. (Issue #32)
|
||||
* Scopes associated to authorization codes are not held in their own table (Issue #44)
|
||||
* Database schema updates.
|
||||
|
||||
## 2.0.5 (released 2013-05-09)
|
||||
|
||||
* Fixed `oauth_session_token_scopes` table primary key
|
||||
* Removed `DEFAULT ''` that has slipped into some tables
|
||||
* Fixed docblock for `SessionInterface::associateRefreshToken()`
|
||||
|
||||
## 2.0.4 (released 2013-05-09)
|
||||
|
||||
* Renamed primary key in oauth_client_endpoints table
|
||||
* Adding missing column to oauth_session_authcodes
|
||||
* SECURITY FIX: A refresh token should be bound to a client ID
|
||||
|
||||
## 2.0.3 (released 2013-05-08)
|
||||
|
||||
* Fixed a link to code in composer.json
|
||||
|
||||
## 2.0.2 (released 2013-05-08)
|
||||
|
||||
* Updated README with wiki guides
|
||||
* Removed `null` as default parameters in some methods in the storage interfaces
|
||||
* Fixed license copyright
|
||||
|
||||
## 2.0.0 (released 2013-05-08)
|
||||
|
||||
**If you're upgrading from v1.0.8 there are lots of breaking changes**
|
||||
|
||||
@@ -8,7 +244,7 @@
|
||||
* Included a PDO driver which implements the storage interfaces so the library is more "get up and go"
|
||||
* Further normalised the database structure so all sessions no longer contain infomation related to authorization grant (which may or may not be enabled)
|
||||
* A session can have multiple associated access tokens
|
||||
* Induvidual grants can have custom expire times for access tokens
|
||||
* Individual grants can have custom expire times for access tokens
|
||||
* Authorization codes now have a TTL of 10 minutes by default (can be manually set)
|
||||
* Refresh tokens now have a TTL of one week by default (can be manually set)
|
||||
* The client credentials grant will no longer gives out refresh tokens as per the specification
|
||||
|
22
CONDUCT.md
Normal file
22
CONDUCT.md
Normal file
@@ -0,0 +1,22 @@
|
||||
# Contributor Code of Conduct
|
||||
|
||||
As contributors and maintainers of this project, and in the interest of fostering an open and welcoming community, we pledge to respect all people who contribute through reporting issues, posting feature requests, updating documentation, submitting pull requests or patches, and other activities.
|
||||
|
||||
We are committed to making participation in this project a harassment-free experience for everyone, regardless of level of experience, gender, gender identity and expression, sexual orientation, disability, personal appearance, body size, race, ethnicity, age, religion, or nationality.
|
||||
|
||||
Examples of unacceptable behavior by participants include:
|
||||
|
||||
* The use of sexualized language or imagery
|
||||
* Personal attacks
|
||||
* Trolling or insulting/derogatory comments
|
||||
* Public or private harassment
|
||||
* Publishing other's private information, such as physical or electronic addresses, without explicit permission
|
||||
* Other unethical or unprofessional conduct.
|
||||
|
||||
Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct. By adopting this Code of Conduct, project maintainers commit themselves to fairly and consistently applying these principles to every aspect of managing this project. Project maintainers who do not follow or enforce the Code of Conduct may be permanently removed from the project team.
|
||||
|
||||
This code of conduct applies both within project spaces and in public spaces when an individual is representing the project or its community in a direct capacity. Personal views, beliefs and values of individuals do not necessarily reflect those of the organisation or affiliated individuals and organisations.
|
||||
|
||||
Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by opening an issue or contacting one or more of the project maintainers.
|
||||
|
||||
This Code of Conduct is adapted from the [Contributor Covenant](http://contributor-covenant.org), version 1.2.0, available at [http://contributor-covenant.org/version/1/2/0/](http://contributor-covenant.org/version/1/2/0/)
|
15
CONTRIBUTING.md
Normal file
15
CONTRIBUTING.md
Normal file
@@ -0,0 +1,15 @@
|
||||
Thanks for contributing to this project.
|
||||
|
||||
|
||||
**Please submit your pull request against the `develop` branch only.**
|
||||
|
||||
|
||||
Please ensure that you run `phpunit` from the project root after you've made any changes.
|
||||
|
||||
If you've added something new please create a new unit test, if you've changed something please update any unit tests as appropritate.
|
||||
|
||||
We're trying to ensure there is **100%** test code coverage (including testing PHP errors and exceptions) so please ensure any new/updated tests cover all of your changes.
|
||||
|
||||
Thank you,
|
||||
|
||||
@alexbilbie
|
@@ -1,6 +1,6 @@
|
||||
MIT License
|
||||
|
||||
Copyright (C) 2013 PHP League of Extraordinary Packages
|
||||
Copyright (C) Alex Bilbie
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
this software and associated documentation files (the "Software"), to deal in
|
79
README.md
79
README.md
@@ -1,67 +1,66 @@
|
||||
# The League of Extraordinary Packages presents: PHP OAuth 2.0 Server
|
||||
# PHP OAuth 2.0 Server
|
||||
|
||||
The goal of this project is to develop a standards compliant [OAuth 2.0](http://tools.ietf.org/wg/oauth/draft-ietf-oauth-v2/) authorization server and resource server.
|
||||
[](https://github.com/thephpleague/oauth2-server/releases)
|
||||
[](LICENSE.md)
|
||||
[](https://travis-ci.org/thephpleague/oauth2-server)
|
||||
[](https://scrutinizer-ci.com/g/thephpleague/oauth2-server/code-structure)
|
||||
[](https://scrutinizer-ci.com/g/thephpleague/oauth2-server)
|
||||
[](https://packagist.org/packages/league/oauth2-server)
|
||||
|
||||
## Package Installation
|
||||
`league/oauth2-server` is a a standards compliant implementation of an [OAuth 2.0](https://tools.ietf.org/html/rfc6749) authorization server written in PHP which makes working with OAuth 2.0 trivial. You can easily configure an OAuth 2.0 server to protect your API with access tokens, or allow clients to request new access tokens and refresh them.
|
||||
|
||||
The framework is provided as a Composer package which can be installed by adding the package to your composer.json file:
|
||||
It supports out of the box the following grants:
|
||||
|
||||
```javascript
|
||||
{
|
||||
"require": {
|
||||
"league/oauth2-server": "2.*"
|
||||
}
|
||||
}
|
||||
```
|
||||
* Authorization code grant
|
||||
* Implicit grant
|
||||
* Client credentials grant
|
||||
* Resource owner password credentials grant
|
||||
* Refresh grant
|
||||
|
||||
---
|
||||
This library was created by Alex Bilbie. Find him on Twitter at [@alexbilbie](https://twitter.com/alexbilbie).
|
||||
|
||||
The library features 100% unit test code coverage. To run the tests yourself run `phpunit` from the project root.
|
||||
## Requirements
|
||||
|
||||
## Current Features
|
||||
The following versions of PHP are supported:
|
||||
|
||||
### Authorization Server
|
||||
* PHP 5.5 (>=5.5.9)
|
||||
* PHP 5.6
|
||||
* PHP 7.0
|
||||
* HHVM
|
||||
|
||||
The authorization server is a flexible class and the following core specification grants are implemented:
|
||||
The `openssl` extension is also required.
|
||||
|
||||
* authorization code ([section 4.1](http://tools.ietf.org/html/rfc6749#section-4.1))
|
||||
* refresh token ([section 6](http://tools.ietf.org/html/rfc6749#section-6))
|
||||
* client credentials ([section 2.3.1](http://tools.ietf.org/html/rfc6749#section-2.3.1))
|
||||
* password (user credentials) ([section 4.3](http://tools.ietf.org/html/rfc6749#section-4.3))
|
||||
## Documentation
|
||||
|
||||
An overview of the different OAuth 2.0 grants can be found in the wiki [https://github.com/php-loep/oauth2-server/wiki/Which-OAuth-2.0-grant-should-I-use%3F](https://github.com/php-loep/oauth2-server/wiki/Which-OAuth-2.0-grant-should-I-use%3F).
|
||||
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/).
|
||||
|
||||
### Resource Server
|
||||
## Changelog
|
||||
|
||||
The resource server allows you to secure your API endpoints by checking for a valid OAuth access token in the request and ensuring the token has the correct scope(s) (i.e. permissions) to access resources.
|
||||
[See the project releases page](https://github.com/thephpleague/oauth2-server/releases)
|
||||
|
||||
### Custom grants
|
||||
## Contributing
|
||||
|
||||
Custom grants can be created easily by implementing an interface. Check out a guide here [https://github.com/php-loep/oauth2-server/wiki/Creating-custom-grants](https://github.com/php-loep/oauth2-server/wiki/Creating-custom-grants).
|
||||
Please see [CONTRIBUTING.md](https://github.com/thephpleague/oauth2-server/blob/master/CONTRIBUTING.md) and [CONDUCT.md](https://github.com/thephpleague/oauth2-server/blob/master/CONDUCT.md) for details.
|
||||
|
||||
### PDO driver
|
||||
## Support
|
||||
|
||||
If you are using MySQL and want to very quickly implement the library then all of the storage interfaces have been implemented with PDO classes. Check out the guide here [https://github.com/php-loep/oauth2-server/wiki/Using-the-PDO-storage-classes](https://github.com/php-loep/oauth2-server/wiki/Using-the-PDO-storage-classes).
|
||||
Bugs and feature request are tracked on [GitHub](https://github.com/thephpleague/oauth2-server/issues).
|
||||
|
||||
## Tutorials and documentation
|
||||
If you have any questions about OAuth _please_ open a ticket here; please **don't** email the address below.
|
||||
|
||||
The wiki has lots of guides on how to use this library, check it out - [https://github.com/php-loep/oauth2-server/wiki](https://github.com/php-loep/oauth2-server/wiki).
|
||||
## Security
|
||||
|
||||
A tutorial on how to use the authorization server can be found on the wiki - (https://github.com/php-loep/oauth2-server/wiki/Developing-an-OAuth-2.0-authorization-server)[https://github.com/php-loep/oauth2-server/wiki/Developing-an-OAuth-2.0-authorization-server].
|
||||
If you discover any security related issues, please email `hello@alexbilbie.com` instead of using the issue tracker.
|
||||
|
||||
A tutorial on how to use the resource server to secure an API server can be found at [https://github.com/php-loep/oauth2-server/wiki/Securing-your-API-with-OAuth-2.0](https://github.com/php-loep/oauth2-server/wiki/Securing-your-API-with-OAuth-2.0).
|
||||
## License
|
||||
|
||||
## Future Goals
|
||||
This package is released under the MIT License. See the bundled [LICENSE](https://github.com/thephpleague/oauth2-server/blob/master/LICENSE) file for details.
|
||||
|
||||
### Authorization Server
|
||||
## Credits
|
||||
|
||||
* Support for [JSON web tokens](http://tools.ietf.org/wg/oauth/draft-ietf-oauth-json-web-token/).
|
||||
* Support for [SAML assertions](http://tools.ietf.org/wg/oauth/draft-ietf-oauth-saml2-bearer/).
|
||||
This code is principally developed and maintained by [Alex Bilbie](https://twitter.com/alexbilbie).
|
||||
|
||||
---
|
||||
Special thanks to [all of these awesome contributors](https://github.com/thephpleague/oauth2-server/contributors)
|
||||
|
||||
The initial code was developed as part of the [Linkey](http://linkey.blogs.lincoln.ac.uk) project which was funded by [JISC](http://jisc.ac.uk) under the Access and Identity Management programme.
|
||||
|
||||
This code is principally developed and maintained by [@alexbilbie](https://twitter.com/alexbilbie).
|
||||
|
||||
A list of contributors can be found at [https://github.com/php-loep/oauth2-server/contributors](https://github.com/php-loep/oauth2-server/contributors).
|
142
build.xml
142
build.xml
@@ -1,142 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project name="PHP OAuth 2.0 Server" default="build">
|
||||
|
||||
<target name="build" depends="prepare,lint,phploc,pdepend,phpmd-ci,phpcs-ci,phpcpd,composer,phpunit,phpdox,phpcb"/>
|
||||
|
||||
<target name="build-parallel" depends="prepare,lint,tools-parallel,phpcb"/>
|
||||
|
||||
<target name="minimal" depends="prepare,lint,phploc,pdepend,phpcpd,composer,phpunit,phpdox,phpcb" />
|
||||
|
||||
<target name="tools-parallel" description="Run tools in parallel">
|
||||
<parallel threadCount="2">
|
||||
<sequential>
|
||||
<antcall target="pdepend"/>
|
||||
<antcall target="phpmd-ci"/>
|
||||
</sequential>
|
||||
<antcall target="phpcpd"/>
|
||||
<antcall target="phpcs-ci"/>
|
||||
<antcall target="phploc"/>
|
||||
<antcall target="phpdox"/>
|
||||
</parallel>
|
||||
</target>
|
||||
|
||||
<target name="clean" description="Cleanup build artifacts">
|
||||
<delete dir="${basedir}/build/api"/>
|
||||
<delete dir="${basedir}/build/code-browser"/>
|
||||
<delete dir="${basedir}/build/coverage"/>
|
||||
<delete dir="${basedir}/build/logs"/>
|
||||
<delete dir="${basedir}/build/pdepend"/>
|
||||
</target>
|
||||
|
||||
<target name="prepare" depends="clean" description="Prepare for build">
|
||||
<mkdir dir="${basedir}/build/api"/>
|
||||
<mkdir dir="${basedir}/build/code-browser"/>
|
||||
<mkdir dir="${basedir}/build/coverage"/>
|
||||
<mkdir dir="${basedir}/build/logs"/>
|
||||
<mkdir dir="${basedir}/build/pdepend"/>
|
||||
<mkdir dir="${basedir}/build/phpdox"/>
|
||||
</target>
|
||||
|
||||
<target name="lint">
|
||||
<apply executable="php" failonerror="true">
|
||||
<arg value="-l" />
|
||||
|
||||
<fileset dir="${basedir}/src">
|
||||
<include name="**/*.php" />
|
||||
<modified />
|
||||
</fileset>
|
||||
</apply>
|
||||
</target>
|
||||
|
||||
<target name="phploc" description="Measure project size using PHPLOC">
|
||||
<exec executable="phploc">
|
||||
<arg value="--log-csv" />
|
||||
<arg value="${basedir}/build/logs/phploc.csv" />
|
||||
<arg path="${basedir}/src" />
|
||||
</exec>
|
||||
</target>
|
||||
|
||||
<target name="pdepend" description="Calculate software metrics using PHP_Depend">
|
||||
<exec executable="pdepend">
|
||||
<arg value="--jdepend-xml=${basedir}/build/logs/jdepend.xml" />
|
||||
<arg value="--jdepend-chart=${basedir}/build/pdepend/dependencies.svg" />
|
||||
<arg value="--overview-pyramid=${basedir}/build/pdepend/overview-pyramid.svg" />
|
||||
<arg path="${basedir}/src" />
|
||||
</exec>
|
||||
</target>
|
||||
|
||||
<target name="phpmd" description="Perform project mess detection using PHPMD and print human readable output. Intended for usage on the command line before committing.">
|
||||
<exec executable="phpmd">
|
||||
<arg path="${basedir}/src" />
|
||||
<arg value="text" />
|
||||
<arg value="${basedir}/build/phpmd.xml" />
|
||||
</exec>
|
||||
</target>
|
||||
|
||||
<target name="phpmd-ci" description="Perform project mess detection using PHPMD creating a log file for the continuous integration server">
|
||||
<exec executable="phpmd">
|
||||
<arg path="${basedir}/src" />
|
||||
<arg value="xml" />
|
||||
<arg value="${basedir}/build/phpmd.xml" />
|
||||
<arg value="--reportfile" />
|
||||
<arg value="${basedir}/build/logs/pmd.xml" />
|
||||
</exec>
|
||||
</target>
|
||||
|
||||
<target name="phpcs" description="Find coding standard violations using PHP_CodeSniffer and print human readable output. Intended for usage on the command line before committing.">
|
||||
<exec executable="phpcs">
|
||||
<arg value="--standard=${basedir}/build/phpcs.xml" />
|
||||
<arg value="--extensions=php" />
|
||||
<arg value="--ignore=third_party/CIUnit" />
|
||||
<arg path="${basedir}/src" />
|
||||
</exec>
|
||||
</target>
|
||||
|
||||
<target name="phpcs-ci" description="Find coding standard violations using PHP_CodeSniffer creating a log file for the continuous integration server">
|
||||
<exec executable="phpcs" output="/dev/null">
|
||||
<arg value="--report=checkstyle" />
|
||||
<arg value="--report-file=${basedir}/build/logs/checkstyle.xml" />
|
||||
<arg value="--standard=${basedir}/build/phpcs.xml" />
|
||||
<arg value="--extensions=php" />
|
||||
<arg value="--ignore=third_party/CIUnit" />
|
||||
<arg path="${basedir}/src" />
|
||||
</exec>
|
||||
</target>
|
||||
|
||||
<target name="phpcpd" description="Find duplicate code using PHPCPD">
|
||||
<exec executable="phpcpd">
|
||||
<arg value="--log-pmd" />
|
||||
<arg value="${basedir}/build/logs/pmd-cpd.xml" />
|
||||
<arg path="${basedir}/src" />
|
||||
</exec>
|
||||
</target>
|
||||
|
||||
<target name="composer" description="Install Composer requirements">
|
||||
<exec executable="composer.phar" failonerror="true">
|
||||
<arg value="install" />
|
||||
<arg value="--dev" />
|
||||
</exec>
|
||||
</target>
|
||||
|
||||
<target name="phpunit" description="Run unit tests with PHPUnit">
|
||||
<exec executable="${basedir}/vendor/bin/phpunit" failonerror="true">
|
||||
<arg value="--configuration" />
|
||||
<arg value="${basedir}/build/phpunit.xml" />
|
||||
</exec>
|
||||
</target>
|
||||
|
||||
<target name="phpdox" description="Generate API documentation using phpDox">
|
||||
<exec executable="phpdox"/>
|
||||
</target>
|
||||
|
||||
<target name="phpcb" description="Aggregate tool output with PHP_CodeBrowser">
|
||||
<exec executable="phpcb">
|
||||
<arg value="--log" />
|
||||
<arg path="${basedir}/build/logs" />
|
||||
<arg value="--source" />
|
||||
<arg path="${basedir}/src" />
|
||||
<arg value="--output" />
|
||||
<arg path="${basedir}/build/code-browser" />
|
||||
</exec>
|
||||
</target>
|
||||
</project>
|
110
composer.json
110
composer.json
@@ -1,47 +1,67 @@
|
||||
{
|
||||
"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.",
|
||||
"version": "2.0.3",
|
||||
"homepage": "https://github.com/php-loep/oauth2-server",
|
||||
"license": "MIT",
|
||||
"require": {
|
||||
"php": ">=5.3.0",
|
||||
"zetacomponents/database": "dev-master"
|
||||
},
|
||||
"require-dev": {
|
||||
"mockery/mockery": ">=0.7.2"
|
||||
},
|
||||
"repositories": [
|
||||
{
|
||||
"type": "git",
|
||||
"url": "https://github.com/php-loep/oauth2-server.git"
|
||||
}
|
||||
],
|
||||
"keywords": [
|
||||
"oauth",
|
||||
"oauth2",
|
||||
"server",
|
||||
"authorization",
|
||||
"authentication",
|
||||
"resource",
|
||||
"api"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Alex Bilbie",
|
||||
"email": "hello@alexbilbie.com",
|
||||
"homepage": "http://www.alexbilbie.com",
|
||||
"role": "Developer"
|
||||
}
|
||||
],
|
||||
"replace": {
|
||||
"lncd/oauth2": "*",
|
||||
"league/oauth2server": "*"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-0": {
|
||||
"League\\OAuth2\\Server": "src/"
|
||||
}
|
||||
},
|
||||
"suggest": {}
|
||||
"name": "league/oauth2-server",
|
||||
"description": "A lightweight and powerful OAuth 2.0 authorization and resource server library with support for all the core specification grants. This library will allow you to secure your API with OAuth and allow your applications users to approve apps that want to access their data from your API.",
|
||||
"homepage": "https://oauth2.thephpleague.com/",
|
||||
"license": "MIT",
|
||||
"require": {
|
||||
"php": ">=5.5.9",
|
||||
"ext-openssl": "*",
|
||||
"league/event": "^2.1",
|
||||
"lcobucci/jwt": "^3.1",
|
||||
"paragonie/random_compat": "^1.1",
|
||||
"psr/http-message": "^1.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "^4.8 || ^5.0",
|
||||
"zendframework/zend-diactoros": "^1.0"
|
||||
},
|
||||
"repositories": [
|
||||
{
|
||||
"type": "git",
|
||||
"url": "https://github.com/thephpleague/oauth2-server.git"
|
||||
}
|
||||
],
|
||||
"keywords": [
|
||||
"oauth",
|
||||
"oauth2",
|
||||
"oauth 2",
|
||||
"oauth 2.0",
|
||||
"server",
|
||||
"auth",
|
||||
"authorization",
|
||||
"authorisation",
|
||||
"authentication",
|
||||
"resource",
|
||||
"api",
|
||||
"auth",
|
||||
"protect",
|
||||
"secure"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Alex Bilbie",
|
||||
"email": "hello@alexbilbie.com",
|
||||
"homepage": "http://www.alexbilbie.com",
|
||||
"role": "Developer"
|
||||
}
|
||||
],
|
||||
"replace": {
|
||||
"lncd/oauth2": "*",
|
||||
"league/oauth2server": "*"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"League\\OAuth2\\Server\\": "src/"
|
||||
}
|
||||
},
|
||||
"autoload-dev": {
|
||||
"psr-4": {
|
||||
"LeagueTests\\": "tests/"
|
||||
}
|
||||
},
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-V5-WIP": "5.0-dev"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
53
examples/README.md
Normal file
53
examples/README.md
Normal file
@@ -0,0 +1,53 @@
|
||||
# Example implementations
|
||||
|
||||
## Installation
|
||||
|
||||
0. Run `composer install` in this directory to install dependencies
|
||||
0. Create a private key `openssl genrsa -out private.key 1024`
|
||||
0. Create a public key `openssl rsa -in private.key -pubout > public.key`
|
||||
0. `cd` into the public directory
|
||||
0. Start a PHP server `php -S localhost:4444`
|
||||
|
||||
## Testing the client credentials grant example
|
||||
|
||||
Send the following cURL request:
|
||||
|
||||
```
|
||||
curl -X "POST" "http://localhost:4444/client_credentials.php/access_token" \
|
||||
-H "Content-Type: application/x-www-form-urlencoded" \
|
||||
-H "Accept: 1.0" \
|
||||
--data-urlencode "grant_type=client_credentials" \
|
||||
--data-urlencode "client_id=myawesomeapp" \
|
||||
--data-urlencode "client_secret=abc123" \
|
||||
--data-urlencode "scope=basic email"
|
||||
```
|
||||
|
||||
## Testing the password grant example
|
||||
|
||||
Send the following cURL request:
|
||||
|
||||
```
|
||||
curl -X "POST" "http://localhost:4444/password.php/access_token" \
|
||||
-H "Content-Type: application/x-www-form-urlencoded" \
|
||||
-H "Accept: 1.0" \
|
||||
--data-urlencode "grant_type=password" \
|
||||
--data-urlencode "client_id=myawesomeapp" \
|
||||
--data-urlencode "client_secret=abc123" \
|
||||
--data-urlencode "username=alex" \
|
||||
--data-urlencode "password=whisky" \
|
||||
--data-urlencode "scope=basic email"
|
||||
```
|
||||
|
||||
## Testing the refresh token grant example
|
||||
|
||||
Send the following cURL request. Replace `{{REFRESH_TOKEN}}` with a refresh token from another grant above:
|
||||
|
||||
```
|
||||
curl -X "POST" "http://localhost:4444/refresh_token.php/access_token" \
|
||||
-H "Content-Type: application/x-www-form-urlencoded" \
|
||||
-H "Accept: 1.0" \
|
||||
--data-urlencode "grant_type=refresh_token" \
|
||||
--data-urlencode "client_id=myawesomeapp" \
|
||||
--data-urlencode "client_secret=abc123" \
|
||||
--data-urlencode "refresh_token={{REFRESH_TOKEN}}"
|
||||
```
|
17
examples/composer.json
Normal file
17
examples/composer.json
Normal file
@@ -0,0 +1,17 @@
|
||||
{
|
||||
"require": {
|
||||
"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/",
|
||||
"League\\OAuth2\\Server\\": "../src/"
|
||||
}
|
||||
}
|
||||
}
|
407
examples/composer.lock
generated
Normal file
407
examples/composer.lock
generated
Normal file
@@ -0,0 +1,407 @@
|
||||
{
|
||||
"_readme": [
|
||||
"This file locks the dependencies of your project to a known state",
|
||||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
|
||||
"This file is @generated automatically"
|
||||
],
|
||||
"hash": "48bcb7a3514d7c7f271c554ba1440124",
|
||||
"content-hash": "e41be75973527cb9d63f27ad14ac8624",
|
||||
"packages": [
|
||||
{
|
||||
"name": "container-interop/container-interop",
|
||||
"version": "1.1.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/container-interop/container-interop.git",
|
||||
"reference": "fc08354828f8fd3245f77a66b9e23a6bca48297e"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/container-interop/container-interop/zipball/fc08354828f8fd3245f77a66b9e23a6bca48297e",
|
||||
"reference": "fc08354828f8fd3245f77a66b9e23a6bca48297e",
|
||||
"shasum": ""
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Interop\\Container\\": "src/Interop/Container/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"description": "Promoting the interoperability of container objects (DIC, SL, etc.)",
|
||||
"time": "2014-12-30 15:22:37"
|
||||
},
|
||||
{
|
||||
"name": "nikic/fast-route",
|
||||
"version": "v0.6.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/nikic/FastRoute.git",
|
||||
"reference": "31fa86924556b80735f98b294a7ffdfb26789f22"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/nikic/FastRoute/zipball/31fa86924556b80735f98b294a7ffdfb26789f22",
|
||||
"reference": "31fa86924556b80735f98b294a7ffdfb26789f22",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=5.4.0"
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"FastRoute\\": "src/"
|
||||
},
|
||||
"files": [
|
||||
"src/functions.php"
|
||||
]
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"BSD-3-Clause"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Nikita Popov",
|
||||
"email": "nikic@php.net"
|
||||
}
|
||||
],
|
||||
"description": "Fast request router for PHP",
|
||||
"keywords": [
|
||||
"router",
|
||||
"routing"
|
||||
],
|
||||
"time": "2015-06-18 19:15:47"
|
||||
},
|
||||
{
|
||||
"name": "pimple/pimple",
|
||||
"version": "v3.0.2",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/silexphp/Pimple.git",
|
||||
"reference": "a30f7d6e57565a2e1a316e1baf2a483f788b258a"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/silexphp/Pimple/zipball/a30f7d6e57565a2e1a316e1baf2a483f788b258a",
|
||||
"reference": "a30f7d6e57565a2e1a316e1baf2a483f788b258a",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=5.3.0"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "3.0.x-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-0": {
|
||||
"Pimple": "src/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Fabien Potencier",
|
||||
"email": "fabien@symfony.com"
|
||||
}
|
||||
],
|
||||
"description": "Pimple, a simple Dependency Injection Container",
|
||||
"homepage": "http://pimple.sensiolabs.org",
|
||||
"keywords": [
|
||||
"container",
|
||||
"dependency injection"
|
||||
],
|
||||
"time": "2015-09-11 15:10:35"
|
||||
},
|
||||
{
|
||||
"name": "psr/http-message",
|
||||
"version": "1.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/php-fig/http-message.git",
|
||||
"reference": "85d63699f0dbedb190bbd4b0d2b9dc707ea4c298"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/php-fig/http-message/zipball/85d63699f0dbedb190bbd4b0d2b9dc707ea4c298",
|
||||
"reference": "85d63699f0dbedb190bbd4b0d2b9dc707ea4c298",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=5.3.0"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "1.0.x-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Psr\\Http\\Message\\": "src/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "PHP-FIG",
|
||||
"homepage": "http://www.php-fig.org/"
|
||||
}
|
||||
],
|
||||
"description": "Common interface for HTTP messages",
|
||||
"keywords": [
|
||||
"http",
|
||||
"http-message",
|
||||
"psr",
|
||||
"psr-7",
|
||||
"request",
|
||||
"response"
|
||||
],
|
||||
"time": "2015-05-04 20:22:00"
|
||||
},
|
||||
{
|
||||
"name": "slim/slim",
|
||||
"version": "3.0.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/slimphp/Slim.git",
|
||||
"reference": "3b06f0f2d84dabbe81b6cea46ace46a3e883253e"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/slimphp/Slim/zipball/3b06f0f2d84dabbe81b6cea46ace46a3e883253e",
|
||||
"reference": "3b06f0f2d84dabbe81b6cea46ace46a3e883253e",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"container-interop/container-interop": "^1.1",
|
||||
"nikic/fast-route": "^0.6",
|
||||
"php": ">=5.5.0",
|
||||
"pimple/pimple": "^3.0",
|
||||
"psr/http-message": "^1.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "^4.0"
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Slim\\": "Slim"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Rob Allen",
|
||||
"email": "rob@akrabat.com",
|
||||
"homepage": "http://akrabat.com"
|
||||
},
|
||||
{
|
||||
"name": "Josh Lockhart",
|
||||
"email": "hello@joshlockhart.com",
|
||||
"homepage": "https://joshlockhart.com"
|
||||
},
|
||||
{
|
||||
"name": "Gabriel Manricks",
|
||||
"email": "gmanricks@me.com",
|
||||
"homepage": "http://gabrielmanricks.com"
|
||||
},
|
||||
{
|
||||
"name": "Andrew Smith",
|
||||
"email": "a.smith@silentworks.co.uk",
|
||||
"homepage": "http://silentworks.co.uk"
|
||||
}
|
||||
],
|
||||
"description": "Slim is a PHP micro framework that helps you quickly write simple yet powerful web applications and APIs",
|
||||
"homepage": "http://slimframework.com",
|
||||
"keywords": [
|
||||
"api",
|
||||
"framework",
|
||||
"micro",
|
||||
"router"
|
||||
],
|
||||
"time": "2015-12-07 14:11:09"
|
||||
}
|
||||
],
|
||||
"packages-dev": [
|
||||
{
|
||||
"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": [],
|
||||
"prefer-stable": false,
|
||||
"prefer-lowest": false,
|
||||
"platform": [],
|
||||
"platform-dev": []
|
||||
}
|
73
examples/public/api.php
Normal file
73
examples/public/api.php
Normal file
@@ -0,0 +1,73 @@
|
||||
<?php
|
||||
|
||||
use League\OAuth2\Server\ResourceServer;
|
||||
use OAuth2ServerExamples\Repositories\AccessTokenRepository;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
use Psr\Http\Message\ServerRequestInterface;
|
||||
use Slim\App;
|
||||
|
||||
include __DIR__ . '/../vendor/autoload.php';
|
||||
|
||||
$app = new App([
|
||||
// Add the resource server to the DI container
|
||||
ResourceServer::class => function () {
|
||||
$server = new ResourceServer(
|
||||
new AccessTokenRepository(), // instance of AccessTokenRepositoryInterface
|
||||
'file://' . __DIR__ . '/../public.key' // the authorization server's public key
|
||||
);
|
||||
|
||||
return $server;
|
||||
},
|
||||
]);
|
||||
|
||||
// Add the resource server middleware which will intercept and validate requests
|
||||
$app->add(
|
||||
new \League\OAuth2\Server\Middleware\ResourceServerMiddleware(
|
||||
$app->getContainer()->get(ResourceServer::class)
|
||||
)
|
||||
);
|
||||
|
||||
// An example endpoint secured with OAuth 2.0
|
||||
$app->get(
|
||||
'/users',
|
||||
function (ServerRequestInterface $request, ResponseInterface $response) use ($app) {
|
||||
|
||||
$users = [
|
||||
[
|
||||
'id' => 123,
|
||||
'name' => 'Alex',
|
||||
'email' => 'alex@thephpleague.com',
|
||||
],
|
||||
[
|
||||
'id' => 124,
|
||||
'name' => 'Frank',
|
||||
'email' => 'frank@thephpleague.com',
|
||||
],
|
||||
[
|
||||
'id' => 125,
|
||||
'name' => 'Phil',
|
||||
'email' => 'phil@thephpleague.com',
|
||||
],
|
||||
];
|
||||
|
||||
// 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 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);
|
||||
}
|
||||
);
|
||||
|
||||
$app->run();
|
108
examples/public/auth_code.php
Normal file
108
examples/public/auth_code.php
Normal file
@@ -0,0 +1,108 @@
|
||||
<?php
|
||||
/**
|
||||
* @author Alex Bilbie <hello@alexbilbie.com>
|
||||
* @copyright Copyright (c) Alex Bilbie
|
||||
* @license http://mit-license.org/
|
||||
*
|
||||
* @link https://github.com/thephpleague/oauth2-server
|
||||
*/
|
||||
|
||||
use League\OAuth2\Server\AuthorizationServer;
|
||||
use League\OAuth2\Server\Exception\OAuthServerException;
|
||||
use League\OAuth2\Server\Grant\AuthCodeGrant;
|
||||
use OAuth2ServerExamples\Entities\UserEntity;
|
||||
use OAuth2ServerExamples\Repositories\AccessTokenRepository;
|
||||
use OAuth2ServerExamples\Repositories\AuthCodeRepository;
|
||||
use OAuth2ServerExamples\Repositories\ClientRepository;
|
||||
use OAuth2ServerExamples\Repositories\RefreshTokenRepository;
|
||||
use OAuth2ServerExamples\Repositories\ScopeRepository;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
use Psr\Http\Message\ServerRequestInterface;
|
||||
use Slim\App;
|
||||
use Zend\Diactoros\Stream;
|
||||
|
||||
include __DIR__ . '/../vendor/autoload.php';
|
||||
|
||||
$app = new App([
|
||||
'settings' => [
|
||||
'displayErrorDetails' => true,
|
||||
],
|
||||
AuthorizationServer::class => function () {
|
||||
// Init our repositories
|
||||
$clientRepository = new ClientRepository();
|
||||
$scopeRepository = new ScopeRepository();
|
||||
$accessTokenRepository = new AccessTokenRepository();
|
||||
$authCodeRepository = new AuthCodeRepository();
|
||||
$refreshTokenRepository = new RefreshTokenRepository();
|
||||
|
||||
$privateKeyPath = 'file://' . __DIR__ . '/../private.key';
|
||||
$publicKeyPath = 'file://' . __DIR__ . '/../public.key';
|
||||
|
||||
// Setup the authorization server
|
||||
$server = new AuthorizationServer(
|
||||
$clientRepository,
|
||||
$accessTokenRepository,
|
||||
$scopeRepository,
|
||||
$privateKeyPath,
|
||||
$publicKeyPath
|
||||
);
|
||||
|
||||
// Enable the authentication code grant on the server with a token TTL of 1 hour
|
||||
$server->enableGrantType(
|
||||
new AuthCodeGrant(
|
||||
$authCodeRepository,
|
||||
$refreshTokenRepository,
|
||||
new \DateInterval('PT10M')
|
||||
),
|
||||
new \DateInterval('PT1H')
|
||||
);
|
||||
|
||||
return $server;
|
||||
},
|
||||
]);
|
||||
|
||||
$app->get('/authorize', function (ServerRequestInterface $request, ResponseInterface $response) use ($app) {
|
||||
/* @var \League\OAuth2\Server\AuthorizationServer $server */
|
||||
$server = $app->getContainer()->get(AuthorizationServer::class);
|
||||
|
||||
try {
|
||||
// Validate the HTTP request and return an AuthorizationRequest object.
|
||||
// The auth request object can be serialized into a user's session
|
||||
$authRequest = $server->validateAuthorizationRequest($request);
|
||||
|
||||
// Once the user has logged in set the user on the AuthorizationRequest
|
||||
$authRequest->setUser(new UserEntity());
|
||||
|
||||
// Once the user has approved or denied the client update the status
|
||||
// (true = approved, false = denied)
|
||||
$authRequest->setAuthorizationApproved(true);
|
||||
|
||||
// Return the HTTP redirect response
|
||||
return $server->completeAuthorizationRequest($authRequest, $response);
|
||||
} catch (OAuthServerException $exception) {
|
||||
return $exception->generateHttpResponse($response);
|
||||
} catch (\Exception $exception) {
|
||||
$body = new Stream('php://temp', 'r+');
|
||||
$body->write($exception->getMessage());
|
||||
|
||||
return $response->withStatus(500)->withBody($body);
|
||||
}
|
||||
});
|
||||
|
||||
$app->post('/access_token', function (ServerRequestInterface $request, ResponseInterface $response) use ($app) {
|
||||
/* @var \League\OAuth2\Server\AuthorizationServer $server */
|
||||
$server = $app->getContainer()->get(AuthorizationServer::class);
|
||||
|
||||
try {
|
||||
return $server->respondToAccessTokenRequest($request, $response);
|
||||
} catch (OAuthServerException $exception) {
|
||||
return $exception->generateHttpResponse($response);
|
||||
} catch (\Exception $exception) {
|
||||
$body = new Stream('php://temp', 'r+');
|
||||
$body->write($exception->getMessage());
|
||||
|
||||
return $response->withStatus(500)->withBody($body);
|
||||
}
|
||||
});
|
||||
|
||||
$app->run();
|
79
examples/public/client_credentials.php
Normal file
79
examples/public/client_credentials.php
Normal file
@@ -0,0 +1,79 @@
|
||||
<?php
|
||||
/**
|
||||
* @author Alex Bilbie <hello@alexbilbie.com>
|
||||
* @copyright Copyright (c) Alex Bilbie
|
||||
* @license http://mit-license.org/
|
||||
*
|
||||
* @link https://github.com/thephpleague/oauth2-server
|
||||
*/
|
||||
|
||||
use League\OAuth2\Server\AuthorizationServer;
|
||||
use League\OAuth2\Server\Exception\OAuthServerException;
|
||||
use OAuth2ServerExamples\Repositories\AccessTokenRepository;
|
||||
use OAuth2ServerExamples\Repositories\ClientRepository;
|
||||
use OAuth2ServerExamples\Repositories\ScopeRepository;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
use Psr\Http\Message\ServerRequestInterface;
|
||||
use Slim\App;
|
||||
use Zend\Diactoros\Stream;
|
||||
|
||||
include __DIR__ . '/../vendor/autoload.php';
|
||||
|
||||
$app = new App([
|
||||
'settings' => [
|
||||
'displayErrorDetails' => true,
|
||||
],
|
||||
AuthorizationServer::class => function () {
|
||||
// Init our repositories
|
||||
$clientRepository = new ClientRepository(); // instance of ClientRepositoryInterface
|
||||
$scopeRepository = new ScopeRepository(); // instance of ScopeRepositoryInterface
|
||||
$accessTokenRepository = new AccessTokenRepository(); // instance of AccessTokenRepositoryInterface
|
||||
|
||||
// Path to public and private keys
|
||||
$privateKey = 'file://'.__DIR__.'/../private.key';
|
||||
//$privateKey = new CryptKey('file://path/to/private.key', 'passphrase'); // if private key has a pass phrase
|
||||
$publicKey = 'file://'.__DIR__.'/../public.key';
|
||||
|
||||
// Setup the authorization server
|
||||
$server = new AuthorizationServer(
|
||||
$clientRepository,
|
||||
$accessTokenRepository,
|
||||
$scopeRepository,
|
||||
$privateKey,
|
||||
$publicKey
|
||||
);
|
||||
|
||||
// Enable the client credentials grant on the server
|
||||
$server->enableGrantType(
|
||||
new \League\OAuth2\Server\Grant\ClientCredentialsGrant(),
|
||||
new \DateInterval('PT1H') // access tokens will expire after 1 hour
|
||||
);
|
||||
|
||||
return $server;
|
||||
},
|
||||
]);
|
||||
|
||||
$app->post('/access_token', function (ServerRequestInterface $request, ResponseInterface $response) use ($app) {
|
||||
|
||||
/* @var \League\OAuth2\Server\AuthorizationServer $server */
|
||||
$server = $app->getContainer()->get(AuthorizationServer::class);
|
||||
|
||||
try {
|
||||
|
||||
// Try to respond to the request
|
||||
return $server->respondToAccessTokenRequest($request, $response);
|
||||
} catch (OAuthServerException $exception) {
|
||||
|
||||
// All instances of OAuthServerException can be formatted into a HTTP response
|
||||
return $exception->generateHttpResponse($response);
|
||||
} catch (\Exception $exception) {
|
||||
|
||||
// Unknown exception
|
||||
$body = new Stream('php://temp', 'r+');
|
||||
$body->write($exception->getMessage());
|
||||
|
||||
return $response->withStatus(500)->withBody($body);
|
||||
}
|
||||
});
|
||||
|
||||
$app->run();
|
81
examples/public/implicit.php
Normal file
81
examples/public/implicit.php
Normal file
@@ -0,0 +1,81 @@
|
||||
<?php
|
||||
/**
|
||||
* @author Alex Bilbie <hello@alexbilbie.com>
|
||||
* @copyright Copyright (c) Alex Bilbie
|
||||
* @license http://mit-license.org/
|
||||
*
|
||||
* @link https://github.com/thephpleague/oauth2-server
|
||||
*/
|
||||
|
||||
use League\OAuth2\Server\AuthorizationServer;
|
||||
use League\OAuth2\Server\Exception\OAuthServerException;
|
||||
use League\OAuth2\Server\Grant\ImplicitGrant;
|
||||
use OAuth2ServerExamples\Entities\UserEntity;
|
||||
use OAuth2ServerExamples\Repositories\AccessTokenRepository;
|
||||
use OAuth2ServerExamples\Repositories\ClientRepository;
|
||||
use OAuth2ServerExamples\Repositories\ScopeRepository;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
use Psr\Http\Message\ServerRequestInterface;
|
||||
use Slim\App;
|
||||
use Zend\Diactoros\Stream;
|
||||
|
||||
include __DIR__ . '/../vendor/autoload.php';
|
||||
|
||||
$app = new App([
|
||||
'settings' => [
|
||||
'displayErrorDetails' => true,
|
||||
],
|
||||
AuthorizationServer::class => function () {
|
||||
// Init our repositories
|
||||
$clientRepository = new ClientRepository();
|
||||
$scopeRepository = new ScopeRepository();
|
||||
$accessTokenRepository = new AccessTokenRepository();
|
||||
|
||||
$privateKeyPath = 'file://' . __DIR__ . '/../private.key';
|
||||
$publicKeyPath = 'file://' . __DIR__ . '/../public.key';
|
||||
|
||||
// Setup the authorization server
|
||||
$server = new AuthorizationServer(
|
||||
$clientRepository,
|
||||
$accessTokenRepository,
|
||||
$scopeRepository,
|
||||
$privateKeyPath,
|
||||
$publicKeyPath
|
||||
);
|
||||
|
||||
// Enable the implicit grant on the server with a token TTL of 1 hour
|
||||
$server->enableGrantType(new ImplicitGrant(new \DateInterval('PT1H')));
|
||||
|
||||
return $server;
|
||||
},
|
||||
]);
|
||||
|
||||
$app->get('/authorize', function (ServerRequestInterface $request, ResponseInterface $response) use ($app) {
|
||||
/* @var \League\OAuth2\Server\AuthorizationServer $server */
|
||||
$server = $app->getContainer()->get(AuthorizationServer::class);
|
||||
|
||||
try {
|
||||
// Validate the HTTP request and return an AuthorizationRequest object.
|
||||
// The auth request object can be serialized into a user's session
|
||||
$authRequest = $server->validateAuthorizationRequest($request);
|
||||
|
||||
// Once the user has logged in set the user on the AuthorizationRequest
|
||||
$authRequest->setUser(new UserEntity());
|
||||
|
||||
// Once the user has approved or denied the client update the status
|
||||
// (true = approved, false = denied)
|
||||
$authRequest->setAuthorizationApproved(true);
|
||||
|
||||
// Return the HTTP redirect response
|
||||
return $server->completeAuthorizationRequest($authRequest, $response);
|
||||
} catch (OAuthServerException $exception) {
|
||||
return $exception->generateHttpResponse($response);
|
||||
} catch (\Exception $exception) {
|
||||
$body = new Stream('php://temp', 'r+');
|
||||
$body->write($exception->getMessage());
|
||||
|
||||
return $response->withStatus(500)->withBody($body);
|
||||
}
|
||||
});
|
||||
|
||||
$app->run();
|
99
examples/public/middleware_use.php
Normal file
99
examples/public/middleware_use.php
Normal file
@@ -0,0 +1,99 @@
|
||||
<?php
|
||||
/**
|
||||
* @author Alex Bilbie <hello@alexbilbie.com>
|
||||
* @copyright Copyright (c) Alex Bilbie
|
||||
* @license http://mit-license.org/
|
||||
*
|
||||
* @link https://github.com/thephpleague/oauth2-server
|
||||
*/
|
||||
|
||||
use League\OAuth2\Server\AuthorizationServer;
|
||||
use League\OAuth2\Server\Grant\AuthCodeGrant;
|
||||
use League\OAuth2\Server\Grant\RefreshTokenGrant;
|
||||
use League\OAuth2\Server\Middleware\AuthorizationServerMiddleware;
|
||||
use League\OAuth2\Server\Middleware\ResourceServerMiddleware;
|
||||
use OAuth2ServerExamples\Repositories\AccessTokenRepository;
|
||||
use OAuth2ServerExamples\Repositories\AuthCodeRepository;
|
||||
use OAuth2ServerExamples\Repositories\ClientRepository;
|
||||
use OAuth2ServerExamples\Repositories\RefreshTokenRepository;
|
||||
use OAuth2ServerExamples\Repositories\ScopeRepository;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
use Psr\Http\Message\ServerRequestInterface;
|
||||
use Slim\App;
|
||||
use Zend\Diactoros\Stream;
|
||||
|
||||
include __DIR__ . '/../vendor/autoload.php';
|
||||
|
||||
$app = new App([
|
||||
'settings' => [
|
||||
'displayErrorDetails' => true,
|
||||
],
|
||||
AuthorizationServer::class => function () {
|
||||
// Init our repositories
|
||||
$clientRepository = new ClientRepository();
|
||||
$accessTokenRepository = new AccessTokenRepository();
|
||||
$scopeRepository = new ScopeRepository();
|
||||
$authCodeRepository = new AuthCodeRepository();
|
||||
$refreshTokenRepository = new RefreshTokenRepository();
|
||||
|
||||
$privateKeyPath = 'file://' . __DIR__ . '/../private.key';
|
||||
$publicKeyPath = 'file://' . __DIR__ . '/../public.key';
|
||||
|
||||
// Setup the authorization server
|
||||
$server = new AuthorizationServer(
|
||||
$clientRepository,
|
||||
$accessTokenRepository,
|
||||
$scopeRepository,
|
||||
$privateKeyPath,
|
||||
$publicKeyPath
|
||||
);
|
||||
|
||||
// Enable the authentication code grant on the server with a token TTL of 1 hour
|
||||
$server->enableGrantType(
|
||||
new AuthCodeGrant(
|
||||
$authCodeRepository,
|
||||
$refreshTokenRepository,
|
||||
new \DateInterval('PT10M')
|
||||
),
|
||||
new \DateInterval('PT1H')
|
||||
);
|
||||
|
||||
// Enable the refresh token grant on the server with a token TTL of 1 month
|
||||
$server->enableGrantType(
|
||||
new RefreshTokenGrant($refreshTokenRepository),
|
||||
new \DateInterval('PT1M')
|
||||
);
|
||||
|
||||
return $server;
|
||||
},
|
||||
]);
|
||||
|
||||
// Access token issuer
|
||||
$app->post('/access_token', function () {
|
||||
})->add(new AuthorizationServerMiddleware($app->getContainer()->get(AuthorizationServer::class)));
|
||||
|
||||
// Secured API
|
||||
$app->group('/api', function () {
|
||||
$this->get('/user', function (ServerRequestInterface $request, ResponseInterface $response) {
|
||||
$params = [];
|
||||
|
||||
if (in_array('basic', $request->getAttribute('oauth_scopes', []))) {
|
||||
$params = [
|
||||
'id' => 1,
|
||||
'name' => 'Alex',
|
||||
'city' => 'London',
|
||||
];
|
||||
}
|
||||
|
||||
if (in_array('email', $request->getAttribute('oauth_scopes', []))) {
|
||||
$params['email'] = 'alex@example.com';
|
||||
}
|
||||
|
||||
$body = new Stream('php://temp', 'r+');
|
||||
$body->write(json_encode($params));
|
||||
|
||||
return $response->withBody($body);
|
||||
});
|
||||
})->add(new ResourceServerMiddleware($app->getContainer()->get(AuthorizationServer::class)));
|
||||
|
||||
$app->run();
|
74
examples/public/password.php
Normal file
74
examples/public/password.php
Normal file
@@ -0,0 +1,74 @@
|
||||
<?php
|
||||
|
||||
use League\OAuth2\Server\AuthorizationServer;
|
||||
use League\OAuth2\Server\Exception\OAuthServerException;
|
||||
use League\OAuth2\Server\Grant\PasswordGrant;
|
||||
use OAuth2ServerExamples\Repositories\AccessTokenRepository;
|
||||
use OAuth2ServerExamples\Repositories\ClientRepository;
|
||||
use OAuth2ServerExamples\Repositories\RefreshTokenRepository;
|
||||
use OAuth2ServerExamples\Repositories\ScopeRepository;
|
||||
use OAuth2ServerExamples\Repositories\UserRepository;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
use Psr\Http\Message\ServerRequestInterface;
|
||||
use Slim\App;
|
||||
|
||||
include __DIR__ . '/../vendor/autoload.php';
|
||||
|
||||
$app = new App([
|
||||
// Add the authorization server to the DI container
|
||||
AuthorizationServer::class => function () {
|
||||
|
||||
// Setup the authorization server
|
||||
$server = new AuthorizationServer(
|
||||
new ClientRepository(), // instance of ClientRepositoryInterface
|
||||
new AccessTokenRepository(), // instance of AccessTokenRepositoryInterface
|
||||
new ScopeRepository(), // instance of ScopeRepositoryInterface
|
||||
'file://'.__DIR__.'/../private.key', // path to private key
|
||||
'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(
|
||||
$grant,
|
||||
new \DateInterval('PT1H') // access tokens will expire after 1 hour
|
||||
);
|
||||
|
||||
return $server;
|
||||
},
|
||||
]);
|
||||
|
||||
$app->post(
|
||||
'/access_token',
|
||||
function (ServerRequestInterface $request, ResponseInterface $response) use ($app) {
|
||||
|
||||
/* @var \League\OAuth2\Server\AuthorizationServer $server */
|
||||
$server = $app->getContainer()->get(AuthorizationServer::class);
|
||||
|
||||
try {
|
||||
|
||||
// Try to respond to the access token request
|
||||
return $server->respondToAccessTokenRequest($request, $response);
|
||||
|
||||
} catch (OAuthServerException $exception) {
|
||||
|
||||
// All instances of OAuthServerException can be converted to a PSR-7 response
|
||||
return $exception->generateHttpResponse($response);
|
||||
|
||||
} catch (\Exception $exception) {
|
||||
|
||||
// Catch unexpected exceptions
|
||||
$body = $response->getBody();
|
||||
$body->write($exception->getMessage());
|
||||
return $response->withStatus(500)->withBody($body);
|
||||
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
$app->run();
|
76
examples/public/refresh_token.php
Normal file
76
examples/public/refresh_token.php
Normal file
@@ -0,0 +1,76 @@
|
||||
<?php
|
||||
/**
|
||||
* @author Alex Bilbie <hello@alexbilbie.com>
|
||||
* @copyright Copyright (c) Alex Bilbie
|
||||
* @license http://mit-license.org/
|
||||
*
|
||||
* @link https://github.com/thephpleague/oauth2-server
|
||||
*/
|
||||
|
||||
use League\OAuth2\Server\AuthorizationServer;
|
||||
use League\OAuth2\Server\Exception\OAuthServerException;
|
||||
use League\OAuth2\Server\Grant\RefreshTokenGrant;
|
||||
use OAuth2ServerExamples\Repositories\AccessTokenRepository;
|
||||
use OAuth2ServerExamples\Repositories\ClientRepository;
|
||||
use OAuth2ServerExamples\Repositories\RefreshTokenRepository;
|
||||
use OAuth2ServerExamples\Repositories\ScopeRepository;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
use Psr\Http\Message\ServerRequestInterface;
|
||||
use Slim\App;
|
||||
use Zend\Diactoros\Stream;
|
||||
|
||||
include __DIR__ . '/../vendor/autoload.php';
|
||||
|
||||
$app = new App([
|
||||
'settings' => [
|
||||
'displayErrorDetails' => true,
|
||||
],
|
||||
AuthorizationServer::class => function () {
|
||||
// Init our repositories
|
||||
$clientRepository = new ClientRepository();
|
||||
$accessTokenRepository = new AccessTokenRepository();
|
||||
$scopeRepository = new ScopeRepository();
|
||||
$refreshTokenRepository = new RefreshTokenRepository();
|
||||
|
||||
$privateKeyPath = 'file://' . __DIR__ . '/../private.key';
|
||||
$publicKeyPath = 'file://' . __DIR__ . '/../public.key';
|
||||
|
||||
// Setup the authorization server
|
||||
$server = new AuthorizationServer(
|
||||
$clientRepository,
|
||||
$accessTokenRepository,
|
||||
$scopeRepository,
|
||||
$privateKeyPath,
|
||||
$publicKeyPath
|
||||
);
|
||||
|
||||
// Enable the refresh token grant on the server
|
||||
$grant = new RefreshTokenGrant($refreshTokenRepository);
|
||||
$grant->setRefreshTokenTTL(new \DateInterval('P1M')); // The refresh token will expire in 1 month
|
||||
|
||||
$server->enableGrantType(
|
||||
$grant,
|
||||
new \DateInterval('PT1H') // The new access token will expire after 1 hour
|
||||
);
|
||||
|
||||
return $server;
|
||||
},
|
||||
]);
|
||||
|
||||
$app->post('/access_token', function (ServerRequestInterface $request, ResponseInterface $response) use ($app) {
|
||||
/* @var \League\OAuth2\Server\AuthorizationServer $server */
|
||||
$server = $app->getContainer()->get(AuthorizationServer::class);
|
||||
|
||||
try {
|
||||
return $server->respondToAccessTokenRequest($request, $response);
|
||||
} catch (OAuthServerException $exception) {
|
||||
return $exception->generateHttpResponse($response);
|
||||
} catch (\Exception $exception) {
|
||||
$body = new Stream('php://temp', 'r+');
|
||||
$body->write($exception->getMessage());
|
||||
|
||||
return $response->withStatus(500)->withBody($body);
|
||||
}
|
||||
});
|
||||
|
||||
$app->run();
|
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;
|
||||
}
|
29
examples/src/Entities/ClientEntity.php
Normal file
29
examples/src/Entities/ClientEntity.php
Normal file
@@ -0,0 +1,29 @@
|
||||
<?php
|
||||
/**
|
||||
* @author Alex Bilbie <hello@alexbilbie.com>
|
||||
* @copyright Copyright (c) Alex Bilbie
|
||||
* @license http://mit-license.org/
|
||||
*
|
||||
* @link https://github.com/thephpleague/oauth2-server
|
||||
*/
|
||||
|
||||
namespace OAuth2ServerExamples\Entities;
|
||||
|
||||
use League\OAuth2\Server\Entities\ClientEntityInterface;
|
||||
use League\OAuth2\Server\Entities\Traits\ClientTrait;
|
||||
use League\OAuth2\Server\Entities\Traits\EntityTrait;
|
||||
|
||||
class ClientEntity implements ClientEntityInterface
|
||||
{
|
||||
use EntityTrait, ClientTrait;
|
||||
|
||||
public function setName($name)
|
||||
{
|
||||
$this->name = $name;
|
||||
}
|
||||
|
||||
public function setRedirectUri($uri)
|
||||
{
|
||||
$this->redirectUri = $uri;
|
||||
}
|
||||
}
|
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;
|
||||
}
|
23
examples/src/Entities/ScopeEntity.php
Normal file
23
examples/src/Entities/ScopeEntity.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 OAuth2ServerExamples\Entities;
|
||||
|
||||
use League\OAuth2\Server\Entities\ScopeEntityInterface;
|
||||
use League\OAuth2\Server\Entities\Traits\EntityTrait;
|
||||
|
||||
class ScopeEntity implements ScopeEntityInterface
|
||||
{
|
||||
use EntityTrait;
|
||||
|
||||
public function jsonSerialize()
|
||||
{
|
||||
return $this->getIdentifier();
|
||||
}
|
||||
}
|
25
examples/src/Entities/UserEntity.php
Normal file
25
examples/src/Entities/UserEntity.php
Normal file
@@ -0,0 +1,25 @@
|
||||
<?php
|
||||
/**
|
||||
* @author Alex Bilbie <hello@alexbilbie.com>
|
||||
* @copyright Copyright (c) Alex Bilbie
|
||||
* @license http://mit-license.org/
|
||||
*
|
||||
* @link https://github.com/thephpleague/oauth2-server
|
||||
*/
|
||||
|
||||
namespace OAuth2ServerExamples\Entities;
|
||||
|
||||
use League\OAuth2\Server\Entities\UserEntityInterface;
|
||||
|
||||
class UserEntity implements UserEntityInterface
|
||||
{
|
||||
/**
|
||||
* Return the user's identifier.
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function getIdentifier()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
}
|
57
examples/src/Repositories/AccessTokenRepository.php
Normal file
57
examples/src/Repositories/AccessTokenRepository.php
Normal file
@@ -0,0 +1,57 @@
|
||||
<?php
|
||||
/**
|
||||
* @author Alex Bilbie <hello@alexbilbie.com>
|
||||
* @copyright Copyright (c) Alex Bilbie
|
||||
* @license http://mit-license.org/
|
||||
*
|
||||
* @link https://github.com/thephpleague/oauth2-server
|
||||
*/
|
||||
|
||||
namespace OAuth2ServerExamples\Repositories;
|
||||
|
||||
use League\OAuth2\Server\Entities\AccessTokenEntityInterface;
|
||||
use League\OAuth2\Server\Entities\ClientEntityInterface;
|
||||
use League\OAuth2\Server\Repositories\AccessTokenRepositoryInterface;
|
||||
use OAuth2ServerExamples\Entities\AccessTokenEntity;
|
||||
|
||||
class AccessTokenRepository implements AccessTokenRepositoryInterface
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function persistNewAccessToken(AccessTokenEntityInterface $accessTokenEntity)
|
||||
{
|
||||
// Some logic here to save the access token to a database
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function revokeAccessToken($tokenId)
|
||||
{
|
||||
// Some logic here to revoke the access token
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function isAccessTokenRevoked($tokenId)
|
||||
{
|
||||
return false; // Access token hasn't been revoked
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getNewToken(ClientEntityInterface $clientEntity, array $scopes, $userIdentifier = null)
|
||||
{
|
||||
$accessToken = new AccessTokenEntity();
|
||||
$accessToken->setClient($clientEntity);
|
||||
foreach ($scopes as $scope) {
|
||||
$accessToken->addScope($scope);
|
||||
}
|
||||
$accessToken->setUserIdentifier($userIdentifier);
|
||||
|
||||
return $accessToken;
|
||||
}
|
||||
}
|
49
examples/src/Repositories/AuthCodeRepository.php
Normal file
49
examples/src/Repositories/AuthCodeRepository.php
Normal file
@@ -0,0 +1,49 @@
|
||||
<?php
|
||||
/**
|
||||
* @author Alex Bilbie <hello@alexbilbie.com>
|
||||
* @copyright Copyright (c) Alex Bilbie
|
||||
* @license http://mit-license.org/
|
||||
*
|
||||
* @link https://github.com/thephpleague/oauth2-server
|
||||
*/
|
||||
|
||||
namespace OAuth2ServerExamples\Repositories;
|
||||
|
||||
use League\OAuth2\Server\Entities\AuthCodeEntityInterface;
|
||||
use League\OAuth2\Server\Repositories\AuthCodeRepositoryInterface;
|
||||
use OAuth2ServerExamples\Entities\AuthCodeEntity;
|
||||
|
||||
class AuthCodeRepository implements AuthCodeRepositoryInterface
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function persistNewAuthCode(AuthCodeEntityInterface $authCodeEntity)
|
||||
{
|
||||
// Some logic to persist the auth code to a database
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function revokeAuthCode($codeId)
|
||||
{
|
||||
// Some logic to revoke the auth code in a database
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function isAuthCodeRevoked($codeId)
|
||||
{
|
||||
return false; // The auth code has not been revoked
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getNewAuthCode()
|
||||
{
|
||||
return new AuthCodeEntity();
|
||||
}
|
||||
}
|
51
examples/src/Repositories/ClientRepository.php
Normal file
51
examples/src/Repositories/ClientRepository.php
Normal file
@@ -0,0 +1,51 @@
|
||||
<?php
|
||||
/**
|
||||
* @author Alex Bilbie <hello@alexbilbie.com>
|
||||
* @copyright Copyright (c) Alex Bilbie
|
||||
* @license http://mit-license.org/
|
||||
*
|
||||
* @link https://github.com/thephpleague/oauth2-server
|
||||
*/
|
||||
|
||||
namespace OAuth2ServerExamples\Repositories;
|
||||
|
||||
use League\OAuth2\Server\Repositories\ClientRepositoryInterface;
|
||||
use OAuth2ServerExamples\Entities\ClientEntity;
|
||||
|
||||
class ClientRepository implements ClientRepositoryInterface
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
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',
|
||||
'is_confidential' => true,
|
||||
],
|
||||
];
|
||||
|
||||
// Check if client is registered
|
||||
if (array_key_exists($clientIdentifier, $clients) === false) {
|
||||
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']);
|
||||
|
||||
return $client;
|
||||
}
|
||||
}
|
49
examples/src/Repositories/RefreshTokenRepository.php
Normal file
49
examples/src/Repositories/RefreshTokenRepository.php
Normal file
@@ -0,0 +1,49 @@
|
||||
<?php
|
||||
/**
|
||||
* @author Alex Bilbie <hello@alexbilbie.com>
|
||||
* @copyright Copyright (c) Alex Bilbie
|
||||
* @license http://mit-license.org/
|
||||
*
|
||||
* @link https://github.com/thephpleague/oauth2-server
|
||||
*/
|
||||
|
||||
namespace OAuth2ServerExamples\Repositories;
|
||||
|
||||
use League\OAuth2\Server\Entities\RefreshTokenEntityInterface;
|
||||
use League\OAuth2\Server\Repositories\RefreshTokenRepositoryInterface;
|
||||
use OAuth2ServerExamples\Entities\RefreshTokenEntity;
|
||||
|
||||
class RefreshTokenRepository implements RefreshTokenRepositoryInterface
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function persistNewRefreshToken(RefreshTokenEntityInterface $refreshTokenEntityInterface)
|
||||
{
|
||||
// Some logic to persist the refresh token in a database
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function revokeRefreshToken($tokenId)
|
||||
{
|
||||
// Some logic to revoke the refresh token in a database
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function isRefreshTokenRevoked($tokenId)
|
||||
{
|
||||
return false; // The refresh token has not been revoked
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getNewRefreshToken()
|
||||
{
|
||||
return new RefreshTokenEntity();
|
||||
}
|
||||
}
|
53
examples/src/Repositories/ScopeRepository.php
Normal file
53
examples/src/Repositories/ScopeRepository.php
Normal file
@@ -0,0 +1,53 @@
|
||||
<?php
|
||||
/**
|
||||
* @author Alex Bilbie <hello@alexbilbie.com>
|
||||
* @copyright Copyright (c) Alex Bilbie
|
||||
* @license http://mit-license.org/
|
||||
*
|
||||
* @link https://github.com/thephpleague/oauth2-server
|
||||
*/
|
||||
|
||||
namespace OAuth2ServerExamples\Repositories;
|
||||
|
||||
use League\OAuth2\Server\Entities\ClientEntityInterface;
|
||||
use League\OAuth2\Server\Repositories\ScopeRepositoryInterface;
|
||||
use OAuth2ServerExamples\Entities\ScopeEntity;
|
||||
|
||||
class ScopeRepository implements ScopeRepositoryInterface
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getScopeEntityByIdentifier($scopeIdentifier)
|
||||
{
|
||||
$scopes = [
|
||||
'basic' => [
|
||||
'description' => 'Basic details about you',
|
||||
],
|
||||
'email' => [
|
||||
'description' => 'Your email address',
|
||||
],
|
||||
];
|
||||
|
||||
if (array_key_exists($scopeIdentifier, $scopes) === false) {
|
||||
return;
|
||||
}
|
||||
|
||||
$scope = new ScopeEntity();
|
||||
$scope->setIdentifier($scopeIdentifier);
|
||||
|
||||
return $scope;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function finalizeScopes(
|
||||
array $scopes,
|
||||
$grantType,
|
||||
ClientEntityInterface $clientEntity,
|
||||
$userIdentifier = null
|
||||
) {
|
||||
return $scopes;
|
||||
}
|
||||
}
|
38
examples/src/Repositories/UserRepository.php
Normal file
38
examples/src/Repositories/UserRepository.php
Normal file
@@ -0,0 +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 OAuth2ServerExamples\Repositories;
|
||||
|
||||
use League\OAuth2\Server\Entities\ClientEntityInterface;
|
||||
use League\OAuth2\Server\Repositories\UserRepositoryInterface;
|
||||
use OAuth2ServerExamples\Entities\ScopeEntity;
|
||||
use OAuth2ServerExamples\Entities\UserEntity;
|
||||
|
||||
class UserRepository implements UserRepositoryInterface
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getUserEntityByUserCredentials(
|
||||
$username,
|
||||
$password,
|
||||
$grantType,
|
||||
ClientEntityInterface $clientEntity
|
||||
) {
|
||||
if ($username === 'alex' && $password === 'whisky') {
|
||||
$scope = new ScopeEntity();
|
||||
$scope->setIdentifier('email');
|
||||
$scopes[] = $scope;
|
||||
|
||||
return new UserEntity();
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
31
phpunit.xml
31
phpunit.xml
@@ -1,31 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<phpunit colors="true" convertNoticesToExceptions="true" convertWarningsToExceptions="true" stopOnError="false" stopOnFailure="false" stopOnIncomplete="false" stopOnSkipped="false" bootstrap="tests/Bootstrap.php">
|
||||
<testsuites>
|
||||
<testsuite name="Authorization Server">
|
||||
<directory suffix="Test.php">tests/authorization</directory>
|
||||
</testsuite>
|
||||
<testsuite name="Resource Server">
|
||||
<directory suffix="Test.php">tests/resource</directory>
|
||||
</testsuite>
|
||||
<testsuite name="Utility Methods">
|
||||
<directory suffix="Test.php">tests/util</directory>
|
||||
</testsuite>
|
||||
</testsuites>
|
||||
<filter>
|
||||
<blacklist>
|
||||
<directory suffix=".php">PEAR_INSTALL_DIR</directory>
|
||||
<directory suffix=".php">PHP_LIBDIR</directory>
|
||||
<directory suffix=".php">vendor/composer</directory>
|
||||
<directory suffix=".php">vendor/mockery</directory>
|
||||
<directory suffix=".php">vendor/phpunit</directory>
|
||||
<directory suffix=".php">tests</directory>
|
||||
<directory suffix=".php">testing</directory>
|
||||
</blacklist>
|
||||
</filter>
|
||||
<logging>
|
||||
<log type="coverage-html" target="build/coverage" title="lncd/OAuth" charset="UTF-8" yui="true" highlight="true" lowUpperBound="50" highLowerBound="90"/>
|
||||
<log type="coverage-text" target="php://stdout" title="lncd/OAuth" charset="UTF-8" yui="true" highlight="true" lowUpperBound="50" highLowerBound="90"/>
|
||||
<log type="coverage-clover" target="build/logs/clover.xml"/>
|
||||
<log type="junit" target="build/logs/junit.xml" logIncompleteSkipped="false"/>
|
||||
</logging>
|
||||
</phpunit>
|
24
phpunit.xml.dist
Normal file
24
phpunit.xml.dist
Normal file
@@ -0,0 +1,24 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<phpunit colors="true" convertNoticesToExceptions="true" convertWarningsToExceptions="true" stopOnError="true"
|
||||
stopOnFailure="true" stopOnIncomplete="false" stopOnSkipped="false" bootstrap="tests/Bootstrap.php">
|
||||
<testsuites>
|
||||
<testsuite name="Tests">
|
||||
<directory>./tests/</directory>
|
||||
</testsuite>
|
||||
</testsuites>
|
||||
<filter>
|
||||
<whitelist addUncoveredFilesFromWhitelist="true">
|
||||
<directory suffix=".php">src</directory>
|
||||
<exclude>
|
||||
<directory suffix=".php">src/ResponseTypes/DefaultTemplates</directory>
|
||||
<directory suffix=".php">src/TemplateRenderer</directory>
|
||||
</exclude>
|
||||
</whitelist>
|
||||
</filter>
|
||||
<logging>
|
||||
<log type="coverage-text" target="php://stdout" title="thephpleague/oauth2-server" charset="UTF-8" yui="true"
|
||||
highlight="true" lowUpperBound="60" highLowerBound="90"/>
|
||||
<log type="coverage-html" target="build/coverage" title="thephpleague/oauth2-server" charset="UTF-8" yui="true"
|
||||
highlight="true" lowUpperBound="60" highLowerBound="90"/>
|
||||
</logging>
|
||||
</phpunit>
|
@@ -1,81 +0,0 @@
|
||||
CREATE TABLE `oauth_clients` (
|
||||
`id` CHAR(40) NOT NULL,
|
||||
`secret` CHAR(40) NOT NULL,
|
||||
`name` VARCHAR(255) NOT NULL,
|
||||
`auto_approve` TINYINT(1) NOT NULL DEFAULT '0',
|
||||
PRIMARY KEY (`id`),
|
||||
UNIQUE KEY `u_oacl_clse_clid` (`secret`,`id`)
|
||||
) ENGINE=INNODB DEFAULT CHARSET=utf8;
|
||||
|
||||
CREATE TABLE `oauth_client_endpoints` (
|
||||
`endpoint_id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
|
||||
`client_id` CHAR(40) NOT NULL,
|
||||
`redirect_uri` VARCHAR(255) NOT NULL,
|
||||
PRIMARY KEY (`endpoint_id`),
|
||||
KEY `i_oaclen_clid` (`client_id`),
|
||||
CONSTRAINT `f_oaclen_clid` FOREIGN KEY (`client_id`) REFERENCES `oauth_clients` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
|
||||
) ENGINE=INNODB DEFAULT CHARSET=utf8;
|
||||
|
||||
CREATE TABLE `oauth_sessions` (
|
||||
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
|
||||
`client_id` char(40) NOT NULL,
|
||||
`owner_type` enum('user','client') NOT NULL DEFAULT 'user',
|
||||
`owner_id` varchar(255) NOT NULL,
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `i_uase_clid_owty_owid` (`client_id`,`owner_type`,`owner_id`),
|
||||
CONSTRAINT `f_oase_clid` FOREIGN KEY (`client_id`) REFERENCES `oauth_clients` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||
|
||||
CREATE TABLE `oauth_session_access_tokens` (
|
||||
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
|
||||
`session_id` int(10) unsigned NOT NULL,
|
||||
`access_token` char(40) NOT NULL DEFAULT '',
|
||||
`access_token_expires` int(10) unsigned NOT NULL,
|
||||
PRIMARY KEY (`id`),
|
||||
UNIQUE KEY `u_oaseacto_acto_seid` (`access_token`,`session_id`),
|
||||
KEY `f_oaseto_seid` (`session_id`),
|
||||
CONSTRAINT `f_oaseto_seid` FOREIGN KEY (`session_id`) REFERENCES `oauth_sessions` (`id`) ON DELETE CASCADE ON UPDATE NO ACTION
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||
|
||||
CREATE TABLE `oauth_session_authcodes` (
|
||||
`session_id` int(10) unsigned NOT NULL,
|
||||
`auth_code` char(40) NOT NULL DEFAULT '',
|
||||
`auth_code_expires` int(10) unsigned NOT NULL,
|
||||
PRIMARY KEY (`session_id`),
|
||||
CONSTRAINT `f_oaseau_seid` FOREIGN KEY (`session_id`) REFERENCES `oauth_sessions` (`id`) ON DELETE CASCADE ON UPDATE NO ACTION
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||
|
||||
CREATE TABLE `oauth_session_redirects` (
|
||||
`session_id` int(10) unsigned NOT NULL,
|
||||
`redirect_uri` varchar(255) NOT NULL DEFAULT '',
|
||||
PRIMARY KEY (`session_id`),
|
||||
CONSTRAINT `f_oasere_seid` FOREIGN KEY (`session_id`) REFERENCES `oauth_sessions` (`id`) ON DELETE CASCADE ON UPDATE NO ACTION
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||
|
||||
CREATE TABLE `oauth_session_refresh_tokens` (
|
||||
`session_access_token_id` int(10) unsigned NOT NULL,
|
||||
`refresh_token` char(40) NOT NULL DEFAULT '',
|
||||
`refresh_token_expires` int(10) unsigned NOT NULL,
|
||||
PRIMARY KEY (`session_access_token_id`),
|
||||
CONSTRAINT `f_oasetore_setoid` FOREIGN KEY (`session_access_token_id`) REFERENCES `oauth_session_access_tokens` (`id`) ON DELETE CASCADE ON UPDATE NO ACTION
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||
|
||||
CREATE TABLE `oauth_scopes` (
|
||||
`id` SMALLINT(5) UNSIGNED NOT NULL AUTO_INCREMENT,
|
||||
`key` VARCHAR(255) NOT NULL,
|
||||
`name` VARCHAR(255) NOT NULL,
|
||||
`description` VARCHAR(255) DEFAULT NULL,
|
||||
PRIMARY KEY (`id`),
|
||||
UNIQUE KEY `u_oasc_sc` (`key`)
|
||||
) ENGINE=INNODB DEFAULT CHARSET=utf8;
|
||||
|
||||
CREATE TABLE `oauth_session_token_scopes` (
|
||||
`session_token_scope_id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
|
||||
`session_access_token_id` int(10) unsigned DEFAULT NULL,
|
||||
`scope_id` smallint(5) unsigned NOT NULL,
|
||||
PRIMARY KEY (`session_token_scope_id`),
|
||||
UNIQUE KEY `u_setosc_setoid_scid` (`session_access_token_id`,`scope_id`),
|
||||
KEY `f_oasetosc_scid` (`scope_id`),
|
||||
CONSTRAINT `f_oasetosc_scid` FOREIGN KEY (`scope_id`) REFERENCES `oauth_scopes` (`id`) ON DELETE CASCADE ON UPDATE NO ACTION,
|
||||
CONSTRAINT `f_oasetosc_setoid` FOREIGN KEY (`session_access_token_id`) REFERENCES `oauth_session_access_tokens` (`id`) ON DELETE CASCADE ON UPDATE NO ACTION
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
214
src/AuthorizationServer.php
Normal file
214
src/AuthorizationServer.php
Normal file
@@ -0,0 +1,214 @@
|
||||
<?php
|
||||
/**
|
||||
* @author Alex Bilbie <hello@alexbilbie.com>
|
||||
* @copyright Copyright (c) Alex Bilbie
|
||||
* @license http://mit-license.org/
|
||||
*
|
||||
* @link https://github.com/thephpleague/oauth2-server
|
||||
*/
|
||||
|
||||
namespace League\OAuth2\Server;
|
||||
|
||||
use DateInterval;
|
||||
use League\Event\EmitterAwareInterface;
|
||||
use League\Event\EmitterAwareTrait;
|
||||
use League\OAuth2\Server\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 \League\OAuth2\Server\Grant\GrantTypeInterface[]
|
||||
*/
|
||||
protected $enabledGrantTypes = [];
|
||||
|
||||
/**
|
||||
* @var \DateInterval[]
|
||||
*/
|
||||
protected $grantTypeAccessTokenTTL = [];
|
||||
|
||||
/**
|
||||
* @var \League\OAuth2\Server\CryptKey
|
||||
*/
|
||||
protected $privateKey;
|
||||
|
||||
/**
|
||||
* @var \League\OAuth2\Server\CryptKey
|
||||
*/
|
||||
protected $publicKey;
|
||||
|
||||
/**
|
||||
* @var ResponseTypeInterface
|
||||
*/
|
||||
protected $responseType;
|
||||
|
||||
/**
|
||||
* @var \League\OAuth2\Server\Repositories\ClientRepositoryInterface
|
||||
*/
|
||||
private $clientRepository;
|
||||
|
||||
/**
|
||||
* @var \League\OAuth2\Server\Repositories\AccessTokenRepositoryInterface
|
||||
*/
|
||||
private $accessTokenRepository;
|
||||
|
||||
/**
|
||||
* @var \League\OAuth2\Server\Repositories\ScopeRepositoryInterface
|
||||
*/
|
||||
private $scopeRepository;
|
||||
|
||||
/**
|
||||
* 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 \League\OAuth2\Server\CryptKey|string $privateKey
|
||||
* @param \League\OAuth2\Server\CryptKey|string $publicKey
|
||||
* @param null|\League\OAuth2\Server\ResponseTypes\ResponseTypeInterface $responseType
|
||||
*/
|
||||
public function __construct(
|
||||
ClientRepositoryInterface $clientRepository,
|
||||
AccessTokenRepositoryInterface $accessTokenRepository,
|
||||
ScopeRepositoryInterface $scopeRepository,
|
||||
$privateKey,
|
||||
$publicKey,
|
||||
ResponseTypeInterface $responseType = null
|
||||
) {
|
||||
$this->clientRepository = $clientRepository;
|
||||
$this->accessTokenRepository = $accessTokenRepository;
|
||||
$this->scopeRepository = $scopeRepository;
|
||||
|
||||
if (!$privateKey instanceof CryptKey) {
|
||||
$privateKey = new CryptKey($privateKey);
|
||||
}
|
||||
$this->privateKey = $privateKey;
|
||||
|
||||
if (!$publicKey instanceof CryptKey) {
|
||||
$publicKey = new CryptKey($publicKey);
|
||||
}
|
||||
$this->publicKey = $publicKey;
|
||||
|
||||
$this->responseType = $responseType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable a grant type on the server.
|
||||
*
|
||||
* @param \League\OAuth2\Server\Grant\GrantTypeInterface $grantType
|
||||
* @param \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 \Psr\Http\Message\ServerRequestInterface $request
|
||||
*
|
||||
* @throws \League\OAuth2\Server\Exception\OAuthServerException
|
||||
*
|
||||
* @return \League\OAuth2\Server\RequestTypes\AuthorizationRequest|null
|
||||
*/
|
||||
public function validateAuthorizationRequest(ServerRequestInterface $request)
|
||||
{
|
||||
$authRequest = null;
|
||||
$enabledGrantTypes = $this->enabledGrantTypes;
|
||||
while ($authRequest === null && $grantType = array_shift($enabledGrantTypes)) {
|
||||
/** @var \League\OAuth2\Server\Grant\GrantTypeInterface $grantType */
|
||||
if ($grantType->canRespondToAuthorizationRequest($request)) {
|
||||
$authRequest = $grantType->validateAuthorizationRequest($request);
|
||||
|
||||
return $authRequest;
|
||||
}
|
||||
}
|
||||
|
||||
throw OAuthServerException::unsupportedGrantType();
|
||||
}
|
||||
|
||||
/**
|
||||
* Complete an authorization request
|
||||
*
|
||||
* @param \League\OAuth2\Server\RequestTypes\AuthorizationRequest $authRequest
|
||||
* @param \Psr\Http\Message\ResponseInterface $response
|
||||
*
|
||||
* @return \League\OAuth2\Server\ResponseTypes\ResponseTypeInterface
|
||||
*/
|
||||
public function completeAuthorizationRequest(AuthorizationRequest $authRequest, ResponseInterface $response)
|
||||
{
|
||||
return $this->enabledGrantTypes[$authRequest->getGrantTypeId()]
|
||||
->completeAuthorizationRequest($authRequest)
|
||||
->generateHttpResponse($response);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return an access token response.
|
||||
*
|
||||
* @param \Psr\Http\Message\ServerRequestInterface $request
|
||||
* @param \Psr\Http\Message\ResponseInterface $response
|
||||
*
|
||||
* @throws \League\OAuth2\Server\Exception\OAuthServerException
|
||||
*
|
||||
* @return \Psr\Http\Message\ResponseInterface
|
||||
*/
|
||||
public function respondToAccessTokenRequest(ServerRequestInterface $request, ResponseInterface $response)
|
||||
{
|
||||
$tokenResponse = null;
|
||||
while ($tokenResponse === null && $grantType = array_shift($this->enabledGrantTypes)) {
|
||||
/** @var \League\OAuth2\Server\Grant\GrantTypeInterface $grantType */
|
||||
if ($grantType->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) {
|
||||
$this->responseType = new BearerTokenResponse();
|
||||
}
|
||||
|
||||
$this->responseType->setPrivateKey($this->privateKey);
|
||||
|
||||
return $this->responseType;
|
||||
}
|
||||
}
|
@@ -0,0 +1,25 @@
|
||||
<?php
|
||||
/**
|
||||
* @author Alex Bilbie <hello@alexbilbie.com>
|
||||
* @copyright Copyright (c) Alex Bilbie
|
||||
* @license http://mit-license.org/
|
||||
*
|
||||
* @link https://github.com/thephpleague/oauth2-server
|
||||
*/
|
||||
|
||||
namespace League\OAuth2\Server\AuthorizationValidators;
|
||||
|
||||
use Psr\Http\Message\ServerRequestInterface;
|
||||
|
||||
interface AuthorizationValidatorInterface
|
||||
{
|
||||
/**
|
||||
* Determine the access token in the authorization header and append OAUth properties to the request
|
||||
* as attributes.
|
||||
*
|
||||
* @param ServerRequestInterface $request
|
||||
*
|
||||
* @return ServerRequestInterface
|
||||
*/
|
||||
public function validateAuthorization(ServerRequestInterface $request);
|
||||
}
|
82
src/AuthorizationValidators/BearerTokenValidator.php
Normal file
82
src/AuthorizationValidators/BearerTokenValidator.php
Normal file
@@ -0,0 +1,82 @@
|
||||
<?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;
|
||||
use Psr\Http\Message\ServerRequestInterface;
|
||||
|
||||
class BearerTokenValidator implements AuthorizationValidatorInterface
|
||||
{
|
||||
use CryptTrait;
|
||||
|
||||
/**
|
||||
* @var \League\OAuth2\Server\Repositories\AccessTokenRepositoryInterface
|
||||
*/
|
||||
private $accessTokenRepository;
|
||||
|
||||
/**
|
||||
* BearerTokenValidator constructor.
|
||||
*
|
||||
* @param \League\OAuth2\Server\Repositories\AccessTokenRepositoryInterface $accessTokenRepository
|
||||
*/
|
||||
public function __construct(AccessTokenRepositoryInterface $accessTokenRepository)
|
||||
{
|
||||
$this->accessTokenRepository = $accessTokenRepository;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function validateAuthorization(ServerRequestInterface $request)
|
||||
{
|
||||
if ($request->hasHeader('authorization') === false) {
|
||||
throw OAuthServerException::accessDenied('Missing "Authorization" header');
|
||||
}
|
||||
|
||||
$header = $request->getHeader('authorization');
|
||||
$jwt = trim(preg_replace('/^(?:\s+)?Bearer\s/', '', $header[0]));
|
||||
|
||||
try {
|
||||
// Attempt to parse and validate the JWT
|
||||
$token = (new Parser())->parse($jwt);
|
||||
if ($token->verify(new Sha256(), $this->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');
|
||||
}
|
||||
|
||||
// Return the request with additional attributes
|
||||
return $request
|
||||
->withAttribute('oauth_access_token_id', $token->getClaim('jti'))
|
||||
->withAttribute('oauth_client_id', $token->getClaim('aud'))
|
||||
->withAttribute('oauth_user_id', $token->getClaim('sub'))
|
||||
->withAttribute('oauth_scopes', $token->getClaim('scopes'));
|
||||
} catch (\InvalidArgumentException $exception) {
|
||||
// JWT couldn't be parsed so return the request as is
|
||||
throw OAuthServerException::accessDenied($exception->getMessage());
|
||||
}
|
||||
}
|
||||
}
|
62
src/CryptKey.php
Normal file
62
src/CryptKey.php
Normal file
@@ -0,0 +1,62 @@
|
||||
<?php
|
||||
/**
|
||||
* Cryptography key holder.
|
||||
*
|
||||
* @author Julián Gutiérrez <juliangut@gmail.com>
|
||||
* @copyright Copyright (c) Alex Bilbie
|
||||
* @license http://mit-license.org/
|
||||
*
|
||||
* @link https://github.com/thephpleague/oauth2-server
|
||||
*/
|
||||
namespace League\OAuth2\Server;
|
||||
|
||||
class CryptKey
|
||||
{
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $keyPath;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $passPhrase;
|
||||
|
||||
/**
|
||||
* @param string $keyPath
|
||||
* @param null|string $passPhrase
|
||||
*/
|
||||
public function __construct($keyPath, $passPhrase = null)
|
||||
{
|
||||
if (strpos($keyPath, 'file://') !== 0) {
|
||||
$keyPath = 'file://' . $keyPath;
|
||||
}
|
||||
|
||||
if (!file_exists($keyPath) || !is_readable($keyPath)) {
|
||||
throw new \LogicException(sprintf('Key path "%s" does not exist or is not readable', $keyPath));
|
||||
}
|
||||
|
||||
$this->keyPath = $keyPath;
|
||||
$this->passPhrase = $passPhrase;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve key path.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getKeyPath()
|
||||
{
|
||||
return $this->keyPath;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve key pass phrase.
|
||||
*
|
||||
* @return null|string
|
||||
*/
|
||||
public function getPassPhrase()
|
||||
{
|
||||
return $this->passPhrase;
|
||||
}
|
||||
}
|
118
src/CryptTrait.php
Normal file
118
src/CryptTrait.php
Normal file
@@ -0,0 +1,118 @@
|
||||
<?php
|
||||
/**
|
||||
* Public/private key encryption.
|
||||
*
|
||||
* @author Alex Bilbie <hello@alexbilbie.com>
|
||||
* @copyright Copyright (c) Alex Bilbie
|
||||
* @license http://mit-license.org/
|
||||
*
|
||||
* @link https://github.com/thephpleague/oauth2-server
|
||||
*/
|
||||
namespace League\OAuth2\Server;
|
||||
|
||||
trait CryptTrait
|
||||
{
|
||||
/**
|
||||
* @var \League\OAuth2\Server\CryptKey
|
||||
*/
|
||||
protected $privateKey;
|
||||
|
||||
/**
|
||||
* @var \League\OAuth2\Server\CryptKey
|
||||
*/
|
||||
protected $publicKey;
|
||||
|
||||
/**
|
||||
* Set path to private key.
|
||||
*
|
||||
* @param \League\OAuth2\Server\CryptKey $privateKey
|
||||
*/
|
||||
public function setPrivateKey(CryptKey $privateKey)
|
||||
{
|
||||
$this->privateKey = $privateKey;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set path to public key.
|
||||
*
|
||||
* @param \League\OAuth2\Server\CryptKey $publicKey
|
||||
*/
|
||||
public function setPublicKey(CryptKey $publicKey)
|
||||
{
|
||||
$this->publicKey = $publicKey;
|
||||
}
|
||||
|
||||
/**
|
||||
* Encrypt data with a private key.
|
||||
*
|
||||
* @param string $unencryptedData
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function encrypt($unencryptedData)
|
||||
{
|
||||
$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->privateKey->getKeyPath())
|
||||
);
|
||||
}
|
||||
|
||||
$chunkSize = ceil($privateKeyDetails['bits'] / 8) - 11;
|
||||
$output = '';
|
||||
|
||||
while ($unencryptedData) {
|
||||
$chunk = substr($unencryptedData, 0, $chunkSize);
|
||||
$unencryptedData = substr($unencryptedData, $chunkSize);
|
||||
if (openssl_private_encrypt($chunk, $encrypted, $privateKey) === false) {
|
||||
// @codeCoverageIgnoreStart
|
||||
throw new \LogicException('Failed to encrypt data');
|
||||
// @codeCoverageIgnoreEnd
|
||||
}
|
||||
$output .= $encrypted;
|
||||
}
|
||||
openssl_pkey_free($privateKey);
|
||||
|
||||
return base64_encode($output);
|
||||
}
|
||||
|
||||
/**
|
||||
* Decrypt data with a public key.
|
||||
*
|
||||
* @param string $encryptedData
|
||||
*
|
||||
* @throws \LogicException
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function decrypt($encryptedData)
|
||||
{
|
||||
$publicKey = openssl_pkey_get_public($this->publicKey->getKeyPath());
|
||||
$publicKeyDetails = @openssl_pkey_get_details($publicKey);
|
||||
if ($publicKeyDetails === null) {
|
||||
throw new \LogicException(
|
||||
sprintf('Could not get details of public key: %s', $this->publicKey->getKeyPath())
|
||||
);
|
||||
}
|
||||
|
||||
$chunkSize = ceil($publicKeyDetails['bits'] / 8);
|
||||
$output = '';
|
||||
|
||||
$encryptedData = base64_decode($encryptedData);
|
||||
|
||||
while ($encryptedData) {
|
||||
$chunk = substr($encryptedData, 0, $chunkSize);
|
||||
$encryptedData = substr($encryptedData, $chunkSize);
|
||||
if (openssl_public_decrypt($chunk, $decrypted, $publicKey/*, OPENSSL_PKCS1_OAEP_PADDING*/) === false) {
|
||||
// @codeCoverageIgnoreStart
|
||||
throw new \LogicException('Failed to decrypt data');
|
||||
// @codeCoverageIgnoreEnd
|
||||
}
|
||||
$output .= $decrypted;
|
||||
}
|
||||
openssl_pkey_free($publicKey);
|
||||
|
||||
return $output;
|
||||
}
|
||||
}
|
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 \League\OAuth2\Server\CryptKey $privateKey
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function convertToJWT(CryptKey $privateKey);
|
||||
}
|
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();
|
||||
}
|
62
src/Entities/RefreshTokenEntityInterface.php
Normal file
62
src/Entities/RefreshTokenEntityInterface.php
Normal file
@@ -0,0 +1,62 @@
|
||||
<?php
|
||||
/**
|
||||
* @author Alex Bilbie <hello@alexbilbie.com>
|
||||
* @copyright Copyright (c) Alex Bilbie
|
||||
* @license http://mit-license.org/
|
||||
*
|
||||
* @link https://github.com/thephpleague/oauth2-server
|
||||
*/
|
||||
|
||||
namespace League\OAuth2\Server\Entities;
|
||||
|
||||
interface RefreshTokenEntityInterface
|
||||
{
|
||||
/**
|
||||
* Get the token's identifier.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getIdentifier();
|
||||
|
||||
/**
|
||||
* Set the token's identifier.
|
||||
*
|
||||
* @param $identifier
|
||||
*/
|
||||
public function setIdentifier($identifier);
|
||||
|
||||
/**
|
||||
* Get the token's expiry date time.
|
||||
*
|
||||
* @return \DateTime
|
||||
*/
|
||||
public function getExpiryDateTime();
|
||||
|
||||
/**
|
||||
* Set the date time when the token expires.
|
||||
*
|
||||
* @param \DateTime $dateTime
|
||||
*/
|
||||
public function setExpiryDateTime(\DateTime $dateTime);
|
||||
|
||||
/**
|
||||
* Set the access token that the refresh token was associated with.
|
||||
*
|
||||
* @param \League\OAuth2\Server\Entities\AccessTokenEntityInterface $accessToken
|
||||
*/
|
||||
public function setAccessToken(AccessTokenEntityInterface $accessToken);
|
||||
|
||||
/**
|
||||
* Get the access token that the refresh token was originally associated with.
|
||||
*
|
||||
* @return \League\OAuth2\Server\Entities\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();
|
||||
}
|
90
src/Entities/TokenInterface.php
Normal file
90
src/Entities/TokenInterface.php
Normal file
@@ -0,0 +1,90 @@
|
||||
<?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 TokenInterface
|
||||
{
|
||||
/**
|
||||
* Get the token's identifier.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getIdentifier();
|
||||
|
||||
/**
|
||||
* Set the token's identifier.
|
||||
*
|
||||
* @param $identifier
|
||||
*/
|
||||
public function setIdentifier($identifier);
|
||||
|
||||
/**
|
||||
* Get the token's expiry date time.
|
||||
*
|
||||
* @return \DateTime
|
||||
*/
|
||||
public function getExpiryDateTime();
|
||||
|
||||
/**
|
||||
* Set the date time when the token expires.
|
||||
*
|
||||
* @param \DateTime $dateTime
|
||||
*/
|
||||
public function setExpiryDateTime(\DateTime $dateTime);
|
||||
|
||||
/**
|
||||
* Set the identifier of the user associated with the token.
|
||||
*
|
||||
* @param string|int $identifier The identifier of the user
|
||||
*/
|
||||
public function setUserIdentifier($identifier);
|
||||
|
||||
/**
|
||||
* Get the token user's identifier.
|
||||
*
|
||||
* @return string|int
|
||||
*/
|
||||
public function getUserIdentifier();
|
||||
|
||||
/**
|
||||
* Get the client that the token was issued to.
|
||||
*
|
||||
* @return ClientEntityInterface
|
||||
*/
|
||||
public function getClient();
|
||||
|
||||
/**
|
||||
* Set the client that the token was issued to.
|
||||
*
|
||||
* @param \League\OAuth2\Server\Entities\ClientEntityInterface $client
|
||||
*/
|
||||
public function setClient(ClientEntityInterface $client);
|
||||
|
||||
/**
|
||||
* Associate a scope with the token.
|
||||
*
|
||||
* @param \League\OAuth2\Server\Entities\ScopeEntityInterface $scope
|
||||
*/
|
||||
public function addScope(ScopeEntityInterface $scope);
|
||||
|
||||
/**
|
||||
* Return an array of scopes associated with the token.
|
||||
*
|
||||
* @return ScopeEntityInterface[]
|
||||
*/
|
||||
public function getScopes();
|
||||
|
||||
/**
|
||||
* Has the token expired?
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isExpired();
|
||||
}
|
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 \League\OAuth2\Server\CryptKey $privateKey
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function convertToJWT(CryptKey $privateKey)
|
||||
{
|
||||
return (new Builder())
|
||||
->setAudience($this->getClient()->getIdentifier())
|
||||
->setId($this->getIdentifier(), true)
|
||||
->setIssuedAt(time())
|
||||
->setNotBefore(time())
|
||||
->setExpiration($this->getExpiryDateTime()->getTimestamp())
|
||||
->setSubject($this->getUserIdentifier())
|
||||
->set('scopes', $this->getScopes())
|
||||
->sign(new Sha256(), new Key($privateKey->getKeyPath(), $privateKey->getPassPhrase()))
|
||||
->getToken();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return ClientEntityInterface
|
||||
*/
|
||||
abstract public function getClient();
|
||||
|
||||
/**
|
||||
* @return \DateTime
|
||||
*/
|
||||
abstract public function getExpiryDateTime();
|
||||
|
||||
/**
|
||||
* @return string|int
|
||||
*/
|
||||
abstract public function getUserIdentifier();
|
||||
|
||||
/**
|
||||
* @return ScopeEntityInterface[]
|
||||
*/
|
||||
abstract public function getScopes();
|
||||
}
|
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;
|
||||
}
|
||||
}
|
40
src/Entities/Traits/ClientTrait.php
Normal file
40
src/Entities/Traits/ClientTrait.php
Normal file
@@ -0,0 +1,40 @@
|
||||
<?php
|
||||
/**
|
||||
* @author Alex Bilbie <hello@alexbilbie.com>
|
||||
* @copyright Copyright (c) Alex Bilbie
|
||||
* @license http://mit-license.org/
|
||||
*
|
||||
* @link https://github.com/thephpleague/oauth2-server
|
||||
*/
|
||||
|
||||
namespace League\OAuth2\Server\Entities\Traits;
|
||||
|
||||
trait ClientTrait
|
||||
{
|
||||
protected $name;
|
||||
|
||||
protected $redirectUri;
|
||||
|
||||
/**
|
||||
* Get the client's name.
|
||||
*
|
||||
* @return string
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public function getName()
|
||||
{
|
||||
return $this->name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the registered redirect URI (as a string).
|
||||
*
|
||||
* Alternatively return an indexed array of redirect URIs.
|
||||
*
|
||||
* @return string|string[]
|
||||
*/
|
||||
public function getRedirectUri()
|
||||
{
|
||||
return $this->redirectUri;
|
||||
}
|
||||
}
|
34
src/Entities/Traits/EntityTrait.php
Normal file
34
src/Entities/Traits/EntityTrait.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 EntityTrait
|
||||
{
|
||||
/*
|
||||
* @var string
|
||||
*/
|
||||
protected $identifier;
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function getIdentifier()
|
||||
{
|
||||
return $this->identifier;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $identifier
|
||||
*/
|
||||
public function setIdentifier($identifier)
|
||||
{
|
||||
$this->identifier = $identifier;
|
||||
}
|
||||
}
|
72
src/Entities/Traits/RefreshTokenTrait.php
Normal file
72
src/Entities/Traits/RefreshTokenTrait.php
Normal file
@@ -0,0 +1,72 @@
|
||||
<?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\AccessTokenEntityInterface;
|
||||
|
||||
trait RefreshTokenTrait
|
||||
{
|
||||
/**
|
||||
* @var AccessTokenEntityInterface
|
||||
*/
|
||||
protected $accessToken;
|
||||
|
||||
/**
|
||||
* @var DateTime
|
||||
*/
|
||||
protected $expiryDateTime;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function setAccessToken(AccessTokenEntityInterface $accessToken)
|
||||
{
|
||||
$this->accessToken = $accessToken;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getAccessToken()
|
||||
{
|
||||
return $this->accessToken;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the token's expiry date time.
|
||||
*
|
||||
* @return DateTime
|
||||
*/
|
||||
public function getExpiryDateTime()
|
||||
{
|
||||
return $this->expiryDateTime;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the date time when the token expires.
|
||||
*
|
||||
* @param DateTime $dateTime
|
||||
*/
|
||||
public function setExpiryDateTime(DateTime $dateTime)
|
||||
{
|
||||
$this->expiryDateTime = $dateTime;
|
||||
}
|
||||
|
||||
/**
|
||||
* Has the token expired?
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isExpired()
|
||||
{
|
||||
return (new DateTime()) > $this->getExpiryDateTime();
|
||||
}
|
||||
}
|
127
src/Entities/Traits/TokenEntityTrait.php
Normal file
127
src/Entities/Traits/TokenEntityTrait.php
Normal file
@@ -0,0 +1,127 @@
|
||||
<?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\ClientEntityInterface;
|
||||
use League\OAuth2\Server\Entities\ScopeEntityInterface;
|
||||
|
||||
trait TokenEntityTrait
|
||||
{
|
||||
/**
|
||||
* @var ScopeEntityInterface[]
|
||||
*/
|
||||
protected $scopes = [];
|
||||
|
||||
/**
|
||||
* @var DateTime
|
||||
*/
|
||||
protected $expiryDateTime;
|
||||
|
||||
/**
|
||||
* @var string|int
|
||||
*/
|
||||
protected $userIdentifier;
|
||||
|
||||
/**
|
||||
* @var ClientEntityInterface
|
||||
*/
|
||||
protected $client;
|
||||
|
||||
/**
|
||||
* Associate a scope with the token.
|
||||
*
|
||||
* @param \League\OAuth2\Server\Entities\ScopeEntityInterface $scope
|
||||
*/
|
||||
public function addScope(ScopeEntityInterface $scope)
|
||||
{
|
||||
$this->scopes[$scope->getIdentifier()] = $scope;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return an array of scopes associated with the token.
|
||||
*
|
||||
* @return ScopeEntityInterface[]
|
||||
*/
|
||||
public function getScopes()
|
||||
{
|
||||
return array_values($this->scopes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the token's expiry date time.
|
||||
*
|
||||
* @return DateTime
|
||||
*/
|
||||
public function getExpiryDateTime()
|
||||
{
|
||||
return $this->expiryDateTime;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the date time when the token expires.
|
||||
*
|
||||
* @param DateTime $dateTime
|
||||
*/
|
||||
public function setExpiryDateTime(DateTime $dateTime)
|
||||
{
|
||||
$this->expiryDateTime = $dateTime;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the identifier of the user associated with the token.
|
||||
*
|
||||
* @param string|int $identifier The identifier of the user
|
||||
*/
|
||||
public function setUserIdentifier($identifier)
|
||||
{
|
||||
$this->userIdentifier = $identifier;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the token user's identifier.
|
||||
*
|
||||
* @return string|int
|
||||
*/
|
||||
public function getUserIdentifier()
|
||||
{
|
||||
return $this->userIdentifier;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the client that the token was issued to.
|
||||
*
|
||||
* @return ClientEntityInterface
|
||||
*/
|
||||
public function getClient()
|
||||
{
|
||||
return $this->client;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the client that the token was issued to.
|
||||
*
|
||||
* @param \League\OAuth2\Server\Entities\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();
|
||||
}
|
274
src/Exception/OAuthServerException.php
Normal file
274
src/Exception/OAuthServerException.php
Normal file
@@ -0,0 +1,274 @@
|
||||
<?php
|
||||
/**
|
||||
* @author Alex Bilbie <hello@alexbilbie.com>
|
||||
* @copyright Copyright (c) Alex Bilbie
|
||||
* @license http://mit-license.org/
|
||||
*
|
||||
* @link https://github.com/thephpleague/oauth2-server
|
||||
*/
|
||||
|
||||
namespace League\OAuth2\Server\Exception;
|
||||
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
|
||||
class OAuthServerException extends \Exception
|
||||
{
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
private $httpStatusCode;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $errorType;
|
||||
|
||||
/**
|
||||
* @var null|string
|
||||
*/
|
||||
private $hint;
|
||||
|
||||
/**
|
||||
* @var null|string
|
||||
*/
|
||||
private $redirectUri;
|
||||
|
||||
/**
|
||||
* Throw a new exception.
|
||||
*
|
||||
* @param string $message Error message
|
||||
* @param int $code Error code
|
||||
* @param string $errorType Error type
|
||||
* @param int $httpStatusCode HTTP status code to send (default = 400)
|
||||
* @param null|string $hint A helper hint
|
||||
* @param null|string $redirectUri A HTTP URI to redirect the user back to
|
||||
*/
|
||||
public function __construct($message, $code, $errorType, $httpStatusCode = 400, $hint = null, $redirectUri = null)
|
||||
{
|
||||
parent::__construct($message, $code);
|
||||
$this->httpStatusCode = $httpStatusCode;
|
||||
$this->errorType = $errorType;
|
||||
$this->hint = $hint;
|
||||
$this->redirectUri = $redirectUri;
|
||||
}
|
||||
|
||||
/**
|
||||
* Unsupported grant type error.
|
||||
*
|
||||
* @return static
|
||||
*/
|
||||
public static function unsupportedGrantType()
|
||||
{
|
||||
$errorMessage = 'The authorization grant type is not supported by the authorization server.';
|
||||
$hint = 'Check the `grant_type` parameter';
|
||||
|
||||
return new static($errorMessage, 2, 'unsupported_grant_type', 400, $hint);
|
||||
}
|
||||
|
||||
/**
|
||||
* Invalid request error.
|
||||
*
|
||||
* @param string $parameter The invalid parameter
|
||||
* @param string|null $hint
|
||||
*
|
||||
* @return static
|
||||
*/
|
||||
public static function invalidRequest($parameter, $hint = null)
|
||||
{
|
||||
$errorMessage = 'The request is missing a required parameter, includes an invalid parameter value, ' .
|
||||
'includes a parameter more than once, or is otherwise malformed.';
|
||||
$hint = ($hint === null) ? sprintf('Check the `%s` parameter', $parameter) : $hint;
|
||||
|
||||
return new static($errorMessage, 3, 'invalid_request', 400, $hint);
|
||||
}
|
||||
|
||||
/**
|
||||
* Invalid client error.
|
||||
*
|
||||
* @return static
|
||||
*/
|
||||
public static function invalidClient()
|
||||
{
|
||||
$errorMessage = 'Client authentication failed';
|
||||
|
||||
return new static($errorMessage, 4, 'invalid_client', 401);
|
||||
}
|
||||
|
||||
/**
|
||||
* Invalid scope error.
|
||||
*
|
||||
* @param string $scope The bad scope
|
||||
* @param null|string $redirectUri A HTTP URI to redirect the user back to
|
||||
*
|
||||
* @return static
|
||||
*/
|
||||
public static function invalidScope($scope, $redirectUri = null)
|
||||
{
|
||||
$errorMessage = 'The requested scope is invalid, unknown, or malformed';
|
||||
$hint = sprintf('Check the `%s` scope', $scope);
|
||||
|
||||
return new static($errorMessage, 5, 'invalid_scope', 400, $hint, $redirectUri);
|
||||
}
|
||||
|
||||
/**
|
||||
* Invalid credentials error.
|
||||
*
|
||||
* @return static
|
||||
*/
|
||||
public static function invalidCredentials()
|
||||
{
|
||||
return new static('The user credentials were incorrect.', 6, 'invalid_credentials', 401);
|
||||
}
|
||||
|
||||
/**
|
||||
* Server error.
|
||||
*
|
||||
* @param $hint
|
||||
*
|
||||
* @return static
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public static function serverError($hint)
|
||||
{
|
||||
return new static(
|
||||
'The authorization server encountered an unexpected condition which prevented it from fulfilling'
|
||||
. ' the request: ' . $hint,
|
||||
7,
|
||||
'server_error',
|
||||
500
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Invalid refresh token.
|
||||
*
|
||||
* @param string|null $hint
|
||||
*
|
||||
* @return static
|
||||
*/
|
||||
public static function invalidRefreshToken($hint = null)
|
||||
{
|
||||
return new static('The refresh token is invalid.', 8, 'invalid_request', 400, $hint);
|
||||
}
|
||||
|
||||
/**
|
||||
* Access denied.
|
||||
*
|
||||
* @param string|null $hint
|
||||
* @param string|null $redirectUri
|
||||
*
|
||||
* @return static
|
||||
*/
|
||||
public static function accessDenied($hint = null, $redirectUri = null)
|
||||
{
|
||||
return new static(
|
||||
'The resource owner or authorization server denied the request.',
|
||||
9,
|
||||
'access_denied',
|
||||
401,
|
||||
$hint,
|
||||
$redirectUri
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getErrorType()
|
||||
{
|
||||
return $this->errorType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate a HTTP response.
|
||||
*
|
||||
* @param \Psr\Http\Message\ResponseInterface $response
|
||||
* @param bool $useFragment True if errors should be in the URI fragment instead of
|
||||
* query string
|
||||
*
|
||||
* @return \Psr\Http\Message\ResponseInterface
|
||||
*/
|
||||
public function generateHttpResponse(ResponseInterface $response, $useFragment = false)
|
||||
{
|
||||
$headers = $this->getHttpHeaders();
|
||||
|
||||
$payload = [
|
||||
'error' => $this->getErrorType(),
|
||||
'message' => $this->getMessage(),
|
||||
];
|
||||
|
||||
if ($this->hint !== null) {
|
||||
$payload['hint'] = $this->hint;
|
||||
}
|
||||
|
||||
if ($this->redirectUri !== null) {
|
||||
if ($useFragment === true) {
|
||||
$this->redirectUri .= (strstr($this->redirectUri, '#') === false) ? '#' : '&';
|
||||
} else {
|
||||
$this->redirectUri .= (strstr($this->redirectUri, '?') === false) ? '?' : '&';
|
||||
}
|
||||
|
||||
return $response->withStatus(302)->withHeader('Location', $this->redirectUri . http_build_query($payload));
|
||||
}
|
||||
|
||||
foreach ($headers as $header => $content) {
|
||||
$response = $response->withHeader($header, $content);
|
||||
}
|
||||
|
||||
$response->getBody()->write(json_encode($payload));
|
||||
|
||||
return $response->withStatus($this->getHttpStatusCode());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all headers that have to be send with the error response.
|
||||
*
|
||||
* @return array Array with header values
|
||||
*/
|
||||
public function getHttpHeaders()
|
||||
{
|
||||
$headers = [
|
||||
'Content-type' => 'application/json',
|
||||
];
|
||||
|
||||
// Add "WWW-Authenticate" header
|
||||
//
|
||||
// RFC 6749, section 5.2.:
|
||||
// "If the client attempted to authenticate via the 'Authorization'
|
||||
// request header field, the authorization server MUST
|
||||
// respond with an HTTP 401 (Unauthorized) status code and
|
||||
// include the "WWW-Authenticate" response header field
|
||||
// matching the authentication scheme used by the client.
|
||||
// @codeCoverageIgnoreStart
|
||||
if ($this->errorType === 'invalid_client') {
|
||||
$authScheme = 'Basic';
|
||||
if (array_key_exists('HTTP_AUTHORIZATION', $_SERVER) !== false
|
||||
&& strpos($_SERVER['HTTP_AUTHORIZATION'], 'Bearer') === 0
|
||||
) {
|
||||
$authScheme = 'Bearer';
|
||||
}
|
||||
$headers[] = 'WWW-Authenticate: ' . $authScheme . ' realm="OAuth"';
|
||||
}
|
||||
// @codeCoverageIgnoreEnd
|
||||
return $headers;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the HTTP status code to send when the exceptions is output.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getHttpStatusCode()
|
||||
{
|
||||
return $this->httpStatusCode;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return null|string
|
||||
*/
|
||||
public function getHint()
|
||||
{
|
||||
return $this->hint;
|
||||
}
|
||||
}
|
29
src/Grant/AbstractAuthorizeGrant.php
Normal file
29
src/Grant/AbstractAuthorizeGrant.php
Normal file
@@ -0,0 +1,29 @@
|
||||
<?php
|
||||
/**
|
||||
* Abstract authorization grant.
|
||||
*
|
||||
* @author Julián Gutiérrez <juliangut@gmail.com>
|
||||
* @copyright Copyright (c) Alex Bilbie
|
||||
* @license http://mit-license.org/
|
||||
*
|
||||
* @link https://github.com/thephpleague/oauth2-server
|
||||
*/
|
||||
|
||||
namespace League\OAuth2\Server\Grant;
|
||||
|
||||
abstract class AbstractAuthorizeGrant extends AbstractGrant
|
||||
{
|
||||
/**
|
||||
* @param string $uri
|
||||
* @param array $params
|
||||
* @param string $queryDelimiter
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function makeRedirectUri($uri, $params = [], $queryDelimiter = '?')
|
||||
{
|
||||
$uri .= (strstr($uri, $queryDelimiter) === false) ? $queryDelimiter : '&';
|
||||
|
||||
return $uri . http_build_query($params);
|
||||
}
|
||||
}
|
430
src/Grant/AbstractGrant.php
Normal file
430
src/Grant/AbstractGrant.php
Normal file
@@ -0,0 +1,430 @@
|
||||
<?php
|
||||
/**
|
||||
* OAuth 2.0 Abstract grant.
|
||||
*
|
||||
* @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\Event\EmitterAwareTrait;
|
||||
use League\OAuth2\Server\CryptTrait;
|
||||
use League\OAuth2\Server\Entities\AccessTokenEntityInterface;
|
||||
use League\OAuth2\Server\Entities\ClientEntityInterface;
|
||||
use League\OAuth2\Server\Entities\ScopeEntityInterface;
|
||||
use League\OAuth2\Server\Exception\OAuthServerException;
|
||||
use League\OAuth2\Server\Repositories\AccessTokenRepositoryInterface;
|
||||
use League\OAuth2\Server\Repositories\AuthCodeRepositoryInterface;
|
||||
use League\OAuth2\Server\Repositories\ClientRepositoryInterface;
|
||||
use League\OAuth2\Server\Repositories\RefreshTokenRepositoryInterface;
|
||||
use League\OAuth2\Server\Repositories\ScopeRepositoryInterface;
|
||||
use League\OAuth2\Server\Repositories\UserRepositoryInterface;
|
||||
use League\OAuth2\Server\RequestEvent;
|
||||
use League\OAuth2\Server\RequestTypes\AuthorizationRequest;
|
||||
use Psr\Http\Message\ServerRequestInterface;
|
||||
|
||||
/**
|
||||
* Abstract grant class.
|
||||
*/
|
||||
abstract class AbstractGrant implements GrantTypeInterface
|
||||
{
|
||||
use EmitterAwareTrait, CryptTrait;
|
||||
|
||||
const SCOPE_DELIMITER_STRING = ' ';
|
||||
|
||||
/**
|
||||
* @var ServerRequestInterface
|
||||
*/
|
||||
protected $request;
|
||||
|
||||
/**
|
||||
* @var ClientRepositoryInterface
|
||||
*/
|
||||
protected $clientRepository;
|
||||
|
||||
/**
|
||||
* @var AccessTokenRepositoryInterface
|
||||
*/
|
||||
protected $accessTokenRepository;
|
||||
|
||||
/**
|
||||
* @var ScopeRepositoryInterface
|
||||
*/
|
||||
protected $scopeRepository;
|
||||
|
||||
/**
|
||||
* @var \League\OAuth2\Server\Repositories\AuthCodeRepositoryInterface
|
||||
*/
|
||||
protected $authCodeRepository;
|
||||
|
||||
/**
|
||||
* @var \League\OAuth2\Server\Repositories\RefreshTokenRepositoryInterface
|
||||
*/
|
||||
protected $refreshTokenRepository;
|
||||
|
||||
/**
|
||||
* @var \League\OAuth2\Server\Repositories\UserRepositoryInterface
|
||||
*/
|
||||
protected $userRepository;
|
||||
|
||||
/**
|
||||
* @var \DateInterval
|
||||
*/
|
||||
protected $refreshTokenTTL;
|
||||
|
||||
/**
|
||||
* @param ClientRepositoryInterface $clientRepository
|
||||
*/
|
||||
public function setClientRepository(ClientRepositoryInterface $clientRepository)
|
||||
{
|
||||
$this->clientRepository = $clientRepository;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param AccessTokenRepositoryInterface $accessTokenRepository
|
||||
*/
|
||||
public function setAccessTokenRepository(AccessTokenRepositoryInterface $accessTokenRepository)
|
||||
{
|
||||
$this->accessTokenRepository = $accessTokenRepository;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ScopeRepositoryInterface $scopeRepository
|
||||
*/
|
||||
public function setScopeRepository(ScopeRepositoryInterface $scopeRepository)
|
||||
{
|
||||
$this->scopeRepository = $scopeRepository;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \League\OAuth2\Server\Repositories\RefreshTokenRepositoryInterface $refreshTokenRepository
|
||||
*/
|
||||
public function setRefreshTokenRepository(RefreshTokenRepositoryInterface $refreshTokenRepository)
|
||||
{
|
||||
$this->refreshTokenRepository = $refreshTokenRepository;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \League\OAuth2\Server\Repositories\AuthCodeRepositoryInterface $authCodeRepository
|
||||
*/
|
||||
public function setAuthCodeRepository(AuthCodeRepositoryInterface $authCodeRepository)
|
||||
{
|
||||
$this->authCodeRepository = $authCodeRepository;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \League\OAuth2\Server\Repositories\UserRepositoryInterface $userRepository
|
||||
*/
|
||||
public function setUserRepository(UserRepositoryInterface $userRepository)
|
||||
{
|
||||
$this->userRepository = $userRepository;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function setRefreshTokenTTL(\DateInterval $refreshTokenTTL)
|
||||
{
|
||||
$this->refreshTokenTTL = $refreshTokenTTL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate the client.
|
||||
*
|
||||
* @param \Psr\Http\Message\ServerRequestInterface $request
|
||||
*
|
||||
* @throws \League\OAuth2\Server\Exception\OAuthServerException
|
||||
*
|
||||
* @return \League\OAuth2\Server\Entities\ClientEntityInterface
|
||||
*/
|
||||
protected function validateClient(ServerRequestInterface $request)
|
||||
{
|
||||
$clientId = $this->getRequestParameter(
|
||||
'client_id',
|
||||
$request,
|
||||
$this->getServerParameter('PHP_AUTH_USER', $request)
|
||||
);
|
||||
if (is_null($clientId)) {
|
||||
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)
|
||||
);
|
||||
|
||||
$client = $this->clientRepository->getClientEntity(
|
||||
$clientId,
|
||||
$this->getIdentifier(),
|
||||
$clientSecret,
|
||||
true
|
||||
);
|
||||
|
||||
if (!$client instanceof ClientEntityInterface) {
|
||||
$this->getEmitter()->emit(new RequestEvent('client.authentication.failed', $request));
|
||||
throw OAuthServerException::invalidClient();
|
||||
}
|
||||
|
||||
// If a redirect URI is provided ensure it matches what is pre-registered
|
||||
$redirectUri = $this->getRequestParameter('redirect_uri', $request, null);
|
||||
if ($redirectUri !== null) {
|
||||
if (
|
||||
is_string($client->getRedirectUri())
|
||||
&& (strcmp($client->getRedirectUri(), $redirectUri) !== 0)
|
||||
) {
|
||||
$this->getEmitter()->emit(new RequestEvent('client.authentication.failed', $request));
|
||||
throw OAuthServerException::invalidClient();
|
||||
} elseif (
|
||||
is_array($client->getRedirectUri())
|
||||
&& in_array($redirectUri, $client->getRedirectUri()) === false
|
||||
) {
|
||||
$this->getEmitter()->emit(new RequestEvent('client.authentication.failed', $request));
|
||||
throw OAuthServerException::invalidClient();
|
||||
}
|
||||
}
|
||||
|
||||
return $client;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate scopes in the request.
|
||||
*
|
||||
* @param string $scopes
|
||||
* @param string $redirectUri
|
||||
*
|
||||
* @throws \League\OAuth2\Server\Exception\OAuthServerException
|
||||
*
|
||||
* @return \League\OAuth2\Server\Entities\ScopeEntityInterface[]
|
||||
*/
|
||||
public function validateScopes(
|
||||
$scopes,
|
||||
$redirectUri = null
|
||||
) {
|
||||
$scopesList = array_filter(
|
||||
explode(self::SCOPE_DELIMITER_STRING, trim($scopes)),
|
||||
function ($scope) {
|
||||
return !empty($scope);
|
||||
}
|
||||
);
|
||||
|
||||
$scopes = [];
|
||||
foreach ($scopesList as $scopeItem) {
|
||||
$scope = $this->scopeRepository->getScopeEntityByIdentifier($scopeItem);
|
||||
|
||||
if (!$scope instanceof ScopeEntityInterface) {
|
||||
throw OAuthServerException::invalidScope($scopeItem, $redirectUri);
|
||||
}
|
||||
|
||||
$scopes[] = $scope;
|
||||
}
|
||||
|
||||
return $scopes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve request parameter.
|
||||
*
|
||||
* @param string $parameter
|
||||
* @param \Psr\Http\Message\ServerRequestInterface $request
|
||||
* @param mixed $default
|
||||
*
|
||||
* @return null|string
|
||||
*/
|
||||
protected function getRequestParameter($parameter, ServerRequestInterface $request, $default = null)
|
||||
{
|
||||
$requestParameters = (array) $request->getParsedBody();
|
||||
|
||||
return isset($requestParameters[$parameter]) ? $requestParameters[$parameter] : $default;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve query string parameter.
|
||||
*
|
||||
* @param string $parameter
|
||||
* @param \Psr\Http\Message\ServerRequestInterface $request
|
||||
* @param mixed $default
|
||||
*
|
||||
* @return null|string
|
||||
*/
|
||||
protected function getQueryStringParameter($parameter, ServerRequestInterface $request, $default = null)
|
||||
{
|
||||
return isset($request->getQueryParams()[$parameter]) ? $request->getQueryParams()[$parameter] : $default;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve cookie parameter.
|
||||
*
|
||||
* @param string $parameter
|
||||
* @param \Psr\Http\Message\ServerRequestInterface $request
|
||||
* @param mixed $default
|
||||
*
|
||||
* @return null|string
|
||||
*/
|
||||
protected function getCookieParameter($parameter, ServerRequestInterface $request, $default = null)
|
||||
{
|
||||
return isset($request->getCookieParams()[$parameter]) ? $request->getCookieParams()[$parameter] : $default;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve server parameter.
|
||||
*
|
||||
* @param string $parameter
|
||||
* @param \Psr\Http\Message\ServerRequestInterface $request
|
||||
* @param mixed $default
|
||||
*
|
||||
* @return null|string
|
||||
*/
|
||||
protected function getServerParameter($parameter, ServerRequestInterface $request, $default = null)
|
||||
{
|
||||
return isset($request->getServerParams()[$parameter]) ? $request->getServerParams()[$parameter] : $default;
|
||||
}
|
||||
|
||||
/**
|
||||
* Issue an access token.
|
||||
*
|
||||
* @param \DateInterval $accessTokenTTL
|
||||
* @param \League\OAuth2\Server\Entities\ClientEntityInterface $client
|
||||
* @param string $userIdentifier
|
||||
* @param \League\OAuth2\Server\Entities\ScopeEntityInterface[] $scopes
|
||||
*
|
||||
* @return \League\OAuth2\Server\Entities\AccessTokenEntityInterface
|
||||
*/
|
||||
protected function issueAccessToken(
|
||||
\DateInterval $accessTokenTTL,
|
||||
ClientEntityInterface $client,
|
||||
$userIdentifier,
|
||||
array $scopes = []
|
||||
) {
|
||||
$accessToken = $this->accessTokenRepository->getNewToken($client, $scopes, $userIdentifier);
|
||||
$accessToken->setClient($client);
|
||||
$accessToken->setUserIdentifier($userIdentifier);
|
||||
$accessToken->setIdentifier($this->generateUniqueIdentifier());
|
||||
$accessToken->setExpiryDateTime((new \DateTime())->add($accessTokenTTL));
|
||||
|
||||
foreach ($scopes as $scope) {
|
||||
$accessToken->addScope($scope);
|
||||
}
|
||||
|
||||
$this->accessTokenRepository->persistNewAccessToken($accessToken);
|
||||
|
||||
return $accessToken;
|
||||
}
|
||||
|
||||
/**
|
||||
* Issue an auth code.
|
||||
*
|
||||
* @param \DateInterval $authCodeTTL
|
||||
* @param \League\OAuth2\Server\Entities\ClientEntityInterface $client
|
||||
* @param string $userIdentifier
|
||||
* @param string $redirectUri
|
||||
* @param \League\OAuth2\Server\Entities\ScopeEntityInterface[] $scopes
|
||||
*
|
||||
* @return \League\OAuth2\Server\Entities\AuthCodeEntityInterface
|
||||
*/
|
||||
protected function issueAuthCode(
|
||||
\DateInterval $authCodeTTL,
|
||||
ClientEntityInterface $client,
|
||||
$userIdentifier,
|
||||
$redirectUri,
|
||||
array $scopes = []
|
||||
) {
|
||||
$authCode = $this->authCodeRepository->getNewAuthCode();
|
||||
$authCode->setIdentifier($this->generateUniqueIdentifier());
|
||||
$authCode->setExpiryDateTime((new \DateTime())->add($authCodeTTL));
|
||||
$authCode->setClient($client);
|
||||
$authCode->setUserIdentifier($userIdentifier);
|
||||
$authCode->setRedirectUri($redirectUri);
|
||||
|
||||
foreach ($scopes as $scope) {
|
||||
$authCode->addScope($scope);
|
||||
}
|
||||
|
||||
$this->authCodeRepository->persistNewAuthCode($authCode);
|
||||
|
||||
return $authCode;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \League\OAuth2\Server\Entities\AccessTokenEntityInterface $accessToken
|
||||
*
|
||||
* @return \League\OAuth2\Server\Entities\RefreshTokenEntityInterface
|
||||
*/
|
||||
protected function issueRefreshToken(AccessTokenEntityInterface $accessToken)
|
||||
{
|
||||
$refreshToken = $this->refreshTokenRepository->getNewRefreshToken();
|
||||
$refreshToken->setIdentifier($this->generateUniqueIdentifier());
|
||||
$refreshToken->setExpiryDateTime((new \DateTime())->add($this->refreshTokenTTL));
|
||||
$refreshToken->setAccessToken($accessToken);
|
||||
|
||||
$this->refreshTokenRepository->persistNewRefreshToken($refreshToken);
|
||||
|
||||
return $refreshToken;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate a new unique identifier.
|
||||
*
|
||||
* @param int $length
|
||||
*
|
||||
* @throws \League\OAuth2\Server\Exception\OAuthServerException
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function generateUniqueIdentifier($length = 40)
|
||||
{
|
||||
try {
|
||||
return bin2hex(random_bytes($length));
|
||||
// @codeCoverageIgnoreStart
|
||||
} catch (\TypeError $e) {
|
||||
throw OAuthServerException::serverError('An unexpected error has occurred');
|
||||
} catch (\Error $e) {
|
||||
throw OAuthServerException::serverError('An unexpected error has occurred');
|
||||
} catch (\Exception $e) {
|
||||
// If you get this message, the CSPRNG failed hard.
|
||||
throw OAuthServerException::serverError('Could not generate a random string');
|
||||
}
|
||||
// @codeCoverageIgnoreEnd
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function canRespondToAccessTokenRequest(ServerRequestInterface $request)
|
||||
{
|
||||
$requestParameters = (array) $request->getParsedBody();
|
||||
|
||||
return (
|
||||
array_key_exists('grant_type', $requestParameters)
|
||||
&& $requestParameters['grant_type'] === $this->getIdentifier()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function canRespondToAuthorizationRequest(ServerRequestInterface $request)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function validateAuthorizationRequest(ServerRequestInterface $request)
|
||||
{
|
||||
throw new \LogicException('This grant cannot validate an authorization request');
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function completeAuthorizationRequest(AuthorizationRequest $authorizationRequest)
|
||||
{
|
||||
throw new \LogicException('This grant cannot complete an authorization request');
|
||||
}
|
||||
}
|
275
src/Grant/AuthCodeGrant.php
Normal file
275
src/Grant/AuthCodeGrant.php
Normal file
@@ -0,0 +1,275 @@
|
||||
<?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\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\RequestEvent;
|
||||
use League\OAuth2\Server\RequestTypes\AuthorizationRequest;
|
||||
use League\OAuth2\Server\ResponseTypes\RedirectResponse;
|
||||
use League\OAuth2\Server\ResponseTypes\ResponseTypeInterface;
|
||||
use Psr\Http\Message\ServerRequestInterface;
|
||||
|
||||
class AuthCodeGrant extends AbstractAuthorizeGrant
|
||||
{
|
||||
/**
|
||||
* @var \DateInterval
|
||||
*/
|
||||
private $authCodeTTL;
|
||||
|
||||
/**
|
||||
* @param \League\OAuth2\Server\Repositories\AuthCodeRepositoryInterface $authCodeRepository
|
||||
* @param \League\OAuth2\Server\Repositories\RefreshTokenRepositoryInterface $refreshTokenRepository
|
||||
* @param \DateInterval $authCodeTTL
|
||||
*/
|
||||
public function __construct(
|
||||
AuthCodeRepositoryInterface $authCodeRepository,
|
||||
RefreshTokenRepositoryInterface $refreshTokenRepository,
|
||||
\DateInterval $authCodeTTL
|
||||
) {
|
||||
$this->setAuthCodeRepository($authCodeRepository);
|
||||
$this->setRefreshTokenRepository($refreshTokenRepository);
|
||||
$this->authCodeTTL = $authCodeTTL;
|
||||
$this->refreshTokenTTL = new \DateInterval('P1M');
|
||||
}
|
||||
|
||||
/**
|
||||
* Respond to an access token request.
|
||||
*
|
||||
* @param \Psr\Http\Message\ServerRequestInterface $request
|
||||
* @param \League\OAuth2\Server\ResponseTypes\ResponseTypeInterface $responseType
|
||||
* @param \DateInterval $accessTokenTTL
|
||||
*
|
||||
* @throws \League\OAuth2\Server\Exception\OAuthServerException
|
||||
*
|
||||
* @return \League\OAuth2\Server\ResponseTypes\ResponseTypeInterface
|
||||
*/
|
||||
public function respondToAccessTokenRequest(
|
||||
ServerRequestInterface $request,
|
||||
ResponseTypeInterface $responseType,
|
||||
DateInterval $accessTokenTTL
|
||||
) {
|
||||
// Validate request
|
||||
$client = $this->validateClient($request);
|
||||
$encryptedAuthCode = $this->getRequestParameter('code', $request, null);
|
||||
|
||||
if ($encryptedAuthCode === null) {
|
||||
throw OAuthServerException::invalidRequest('code');
|
||||
}
|
||||
|
||||
// Validate the authorization code
|
||||
try {
|
||||
$authCodePayload = json_decode($this->decrypt($encryptedAuthCode));
|
||||
if (time() > $authCodePayload->expire_time) {
|
||||
throw OAuthServerException::invalidRequest('code', 'Authorization code has expired');
|
||||
}
|
||||
|
||||
if ($this->authCodeRepository->isAuthCodeRevoked($authCodePayload->auth_code_id) === true) {
|
||||
throw OAuthServerException::invalidRequest('code', 'Authorization code has been revoked');
|
||||
}
|
||||
|
||||
if ($authCodePayload->client_id !== $client->getIdentifier()) {
|
||||
throw OAuthServerException::invalidRequest('code', 'Authorization code was not issued to this client');
|
||||
}
|
||||
|
||||
// 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');
|
||||
}
|
||||
|
||||
$scopes = [];
|
||||
foreach ($authCodePayload->scopes as $scopeId) {
|
||||
$scope = $this->scopeRepository->getScopeEntityByIdentifier($scopeId);
|
||||
|
||||
if (!$scope instanceof ScopeEntityInterface) {
|
||||
// @codeCoverageIgnoreStart
|
||||
throw OAuthServerException::invalidScope($scopeId);
|
||||
// @codeCoverageIgnoreEnd
|
||||
}
|
||||
|
||||
$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');
|
||||
}
|
||||
|
||||
// Issue and persist access + refresh tokens
|
||||
$accessToken = $this->issueAccessToken($accessTokenTTL, $client, $authCodePayload->user_id, $scopes);
|
||||
$refreshToken = $this->issueRefreshToken($accessToken);
|
||||
|
||||
// Inject tokens into response type
|
||||
$responseType->setAccessToken($accessToken);
|
||||
$responseType->setRefreshToken($refreshToken);
|
||||
|
||||
// Revoke used auth code
|
||||
$this->authCodeRepository->revokeAuthCode($authCodePayload->auth_code_id);
|
||||
|
||||
return $responseType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the grant identifier that can be used in matching up requests.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getIdentifier()
|
||||
{
|
||||
return 'authorization_code';
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function canRespondToAuthorizationRequest(ServerRequestInterface $request)
|
||||
{
|
||||
return (
|
||||
array_key_exists('response_type', $request->getQueryParams())
|
||||
&& $request->getQueryParams()['response_type'] === 'code'
|
||||
&& isset($request->getQueryParams()['client_id'])
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function validateAuthorizationRequest(ServerRequestInterface $request)
|
||||
{
|
||||
$clientId = $this->getQueryStringParameter(
|
||||
'client_id',
|
||||
$request,
|
||||
$this->getServerParameter('PHP_AUTH_USER', $request)
|
||||
);
|
||||
if (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('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('client.authentication.failed', $request));
|
||||
throw OAuthServerException::invalidClient();
|
||||
} elseif (
|
||||
is_array($client->getRedirectUri())
|
||||
&& in_array($redirectUri, $client->getRedirectUri()) === false
|
||||
) {
|
||||
$this->getEmitter()->emit(new RequestEvent('client.authentication.failed', $request));
|
||||
throw OAuthServerException::invalidClient();
|
||||
}
|
||||
}
|
||||
|
||||
$scopes = $this->validateScopes(
|
||||
$this->getQueryStringParameter('scope', $request),
|
||||
is_array($client->getRedirectUri())
|
||||
? $client->getRedirectUri()[0]
|
||||
: $client->getRedirectUri()
|
||||
);
|
||||
|
||||
$stateParameter = $this->getQueryStringParameter('state', $request);
|
||||
|
||||
$authorizationRequest = new AuthorizationRequest();
|
||||
$authorizationRequest->setGrantTypeId($this->getIdentifier());
|
||||
$authorizationRequest->setClient($client);
|
||||
$authorizationRequest->setRedirectUri($redirectUri);
|
||||
$authorizationRequest->setState($stateParameter);
|
||||
$authorizationRequest->setScopes($scopes);
|
||||
|
||||
return $authorizationRequest;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function completeAuthorizationRequest(AuthorizationRequest $authorizationRequest)
|
||||
{
|
||||
if ($authorizationRequest->getUser() instanceof UserEntityInterface === false) {
|
||||
throw new \LogicException('An instance of UserEntityInterface should be set on the AuthorizationRequest');
|
||||
}
|
||||
|
||||
$finalRedirectUri = ($authorizationRequest->getRedirectUri() === null)
|
||||
? is_array($authorizationRequest->getClient()->getRedirectUri())
|
||||
? $authorizationRequest->getClient()->getRedirectUri()[0]
|
||||
: $authorizationRequest->getClient()->getRedirectUri()
|
||||
: $authorizationRequest->getRedirectUri();
|
||||
|
||||
// The user approved the client, redirect them back with an auth code
|
||||
if ($authorizationRequest->isAuthorizationApproved() === true) {
|
||||
$authCode = $this->issueAuthCode(
|
||||
$this->authCodeTTL,
|
||||
$authorizationRequest->getClient(),
|
||||
$authorizationRequest->getUser()->getIdentifier(),
|
||||
$authorizationRequest->getRedirectUri(),
|
||||
$authorizationRequest->getScopes()
|
||||
);
|
||||
|
||||
$response = new RedirectResponse();
|
||||
$response->setRedirectUri(
|
||||
$this->makeRedirectUri(
|
||||
$finalRedirectUri,
|
||||
[
|
||||
'code' => $this->encrypt(
|
||||
json_encode(
|
||||
[
|
||||
'client_id' => $authCode->getClient()->getIdentifier(),
|
||||
'redirect_uri' => $authCode->getRedirectUri(),
|
||||
'auth_code_id' => $authCode->getIdentifier(),
|
||||
'scopes' => $authCode->getScopes(),
|
||||
'user_id' => $authCode->getUserIdentifier(),
|
||||
'expire_time' => (new \DateTime())->add($this->authCodeTTL)->format('U'),
|
||||
]
|
||||
)
|
||||
),
|
||||
'state' => $authorizationRequest->getState(),
|
||||
]
|
||||
)
|
||||
);
|
||||
|
||||
return $response;
|
||||
}
|
||||
|
||||
// The user denied the client, redirect them back with an error
|
||||
throw OAuthServerException::accessDenied(
|
||||
'The user denied the request',
|
||||
$finalRedirectUri
|
||||
);
|
||||
}
|
||||
}
|
52
src/Grant/ClientCredentialsGrant.php
Normal file
52
src/Grant/ClientCredentialsGrant.php
Normal file
@@ -0,0 +1,52 @@
|
||||
<?php
|
||||
/**
|
||||
* OAuth 2.0 Client credentials grant.
|
||||
*
|
||||
* @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\ResponseTypes\ResponseTypeInterface;
|
||||
use Psr\Http\Message\ServerRequestInterface;
|
||||
|
||||
/**
|
||||
* Client credentials grant class.
|
||||
*/
|
||||
class ClientCredentialsGrant extends AbstractGrant
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function respondToAccessTokenRequest(
|
||||
ServerRequestInterface $request,
|
||||
ResponseTypeInterface $responseType,
|
||||
\DateInterval $accessTokenTTL
|
||||
) {
|
||||
// Validate request
|
||||
$client = $this->validateClient($request);
|
||||
$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, null, $scopes);
|
||||
|
||||
// Inject access token into response type
|
||||
$responseType->setAccessToken($accessToken);
|
||||
|
||||
return $responseType;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getIdentifier()
|
||||
{
|
||||
return 'client_credentials';
|
||||
}
|
||||
}
|
134
src/Grant/GrantTypeInterface.php
Normal file
134
src/Grant/GrantTypeInterface.php
Normal file
@@ -0,0 +1,134 @@
|
||||
<?php
|
||||
/**
|
||||
* OAuth 2.0 Grant type 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\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;
|
||||
|
||||
/**
|
||||
* Grant type interface.
|
||||
*/
|
||||
interface GrantTypeInterface extends EmitterAwareInterface
|
||||
{
|
||||
/**
|
||||
* Set refresh token TTL.
|
||||
*
|
||||
* @param \DateInterval $refreshTokenTTL
|
||||
*/
|
||||
public function setRefreshTokenTTL(\DateInterval $refreshTokenTTL);
|
||||
|
||||
/**
|
||||
* Return the grant identifier that can be used in matching up requests.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getIdentifier();
|
||||
|
||||
/**
|
||||
* Respond to an incoming request.
|
||||
*
|
||||
* @param \Psr\Http\Message\ServerRequestInterface $request
|
||||
* @param \League\OAuth2\Server\ResponseTypes\ResponseTypeInterface $responseType
|
||||
* @param \DateInterval $accessTokenTTL
|
||||
*
|
||||
* @return \League\OAuth2\Server\ResponseTypes\ResponseTypeInterface
|
||||
*/
|
||||
public function respondToAccessTokenRequest(
|
||||
ServerRequestInterface $request,
|
||||
ResponseTypeInterface $responseType,
|
||||
\DateInterval $accessTokenTTL
|
||||
);
|
||||
|
||||
/**
|
||||
* The grant type should return true if it is able to response to an authorization request
|
||||
*
|
||||
* @param \Psr\Http\Message\ServerRequestInterface $request
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function canRespondToAuthorizationRequest(ServerRequestInterface $request);
|
||||
|
||||
/**
|
||||
* If the grant can respond to an authorization request this method should be called to validate the parameters of
|
||||
* the request.
|
||||
*
|
||||
* If the validation is successful an AuthorizationRequest object will be returned. This object can be safely
|
||||
* serialized in a user's session, and can be used during user authentication and authorization.
|
||||
*
|
||||
* @param \Psr\Http\Message\ServerRequestInterface $request
|
||||
*
|
||||
* @return AuthorizationRequest
|
||||
*/
|
||||
public function validateAuthorizationRequest(ServerRequestInterface $request);
|
||||
|
||||
/**
|
||||
* Once a user has authenticated and authorized the client the grant can complete the authorization request.
|
||||
* The AuthorizationRequest object's $userId property must be set to the authenticated user and the
|
||||
* $authorizationApproved property must reflect their desire to authorize or deny the client.
|
||||
*
|
||||
* @param \League\OAuth2\Server\RequestTypes\AuthorizationRequest $authorizationRequest
|
||||
*
|
||||
* @return \League\OAuth2\Server\ResponseTypes\ResponseTypeInterface
|
||||
*/
|
||||
public function completeAuthorizationRequest(AuthorizationRequest $authorizationRequest);
|
||||
|
||||
/**
|
||||
* The grant type should return true if it is able to respond to this request.
|
||||
*
|
||||
* For example most grant types will check that the $_POST['grant_type'] property matches it's identifier property.
|
||||
*
|
||||
* @param \Psr\Http\Message\ServerRequestInterface $request
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function canRespondToAccessTokenRequest(ServerRequestInterface $request);
|
||||
|
||||
/**
|
||||
* Set the client repository.
|
||||
*
|
||||
* @param \League\OAuth2\Server\Repositories\ClientRepositoryInterface $clientRepository
|
||||
*/
|
||||
public function setClientRepository(ClientRepositoryInterface $clientRepository);
|
||||
|
||||
/**
|
||||
* Set the access token repository.
|
||||
*
|
||||
* @param \League\OAuth2\Server\Repositories\AccessTokenRepositoryInterface $accessTokenRepository
|
||||
*/
|
||||
public function setAccessTokenRepository(AccessTokenRepositoryInterface $accessTokenRepository);
|
||||
|
||||
/**
|
||||
* Set the scope repository.
|
||||
*
|
||||
* @param \League\OAuth2\Server\Repositories\ScopeRepositoryInterface $scopeRepository
|
||||
*/
|
||||
public function setScopeRepository(ScopeRepositoryInterface $scopeRepository);
|
||||
|
||||
/**
|
||||
* Set the path to the private key.
|
||||
*
|
||||
* @param \League\OAuth2\Server\CryptKey $privateKey
|
||||
*/
|
||||
public function setPrivateKey(CryptKey $privateKey);
|
||||
|
||||
/**
|
||||
* Set the path to the public key.
|
||||
*
|
||||
* @param \League\OAuth2\Server\CryptKey $publicKey
|
||||
*/
|
||||
public function setPublicKey(CryptKey $publicKey);
|
||||
}
|
213
src/Grant/ImplicitGrant.php
Normal file
213
src/Grant/ImplicitGrant.php
Normal file
@@ -0,0 +1,213 @@
|
||||
<?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\ClientEntityInterface;
|
||||
use League\OAuth2\Server\Entities\UserEntityInterface;
|
||||
use League\OAuth2\Server\Exception\OAuthServerException;
|
||||
use League\OAuth2\Server\Repositories\RefreshTokenRepositoryInterface;
|
||||
use League\OAuth2\Server\RequestEvent;
|
||||
use League\OAuth2\Server\RequestTypes\AuthorizationRequest;
|
||||
use League\OAuth2\Server\ResponseTypes\RedirectResponse;
|
||||
use League\OAuth2\Server\ResponseTypes\ResponseTypeInterface;
|
||||
use Psr\Http\Message\ServerRequestInterface;
|
||||
|
||||
class ImplicitGrant extends AbstractAuthorizeGrant
|
||||
{
|
||||
/**
|
||||
* @var \DateInterval
|
||||
*/
|
||||
private $accessTokenTTL;
|
||||
|
||||
/**
|
||||
* @param \DateInterval $accessTokenTTL
|
||||
*/
|
||||
public function __construct(\DateInterval $accessTokenTTL)
|
||||
{
|
||||
$this->accessTokenTTL = $accessTokenTTL;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \DateInterval $refreshTokenTTL
|
||||
*
|
||||
* @throw \LogicException
|
||||
*/
|
||||
public function setRefreshTokenTTL(\DateInterval $refreshTokenTTL)
|
||||
{
|
||||
throw new \LogicException('The Implicit Grant does nto return refresh tokens');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \League\OAuth2\Server\Repositories\RefreshTokenRepositoryInterface $refreshTokenRepository
|
||||
*
|
||||
* @throw \LogicException
|
||||
*/
|
||||
public function setRefreshTokenRepository(RefreshTokenRepositoryInterface $refreshTokenRepository)
|
||||
{
|
||||
throw new \LogicException('The Implicit Grant does nto return refresh tokens');
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function canRespondToAccessTokenRequest(ServerRequestInterface $request)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the grant identifier that can be used in matching up requests.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getIdentifier()
|
||||
{
|
||||
return 'implicit';
|
||||
}
|
||||
|
||||
/**
|
||||
* Respond to an incoming request.
|
||||
*
|
||||
* @param \Psr\Http\Message\ServerRequestInterface $request
|
||||
* @param \League\OAuth2\Server\ResponseTypes\ResponseTypeInterface $responseType
|
||||
* @param \DateInterval $accessTokenTTL
|
||||
*
|
||||
* @return \League\OAuth2\Server\ResponseTypes\ResponseTypeInterface
|
||||
*/
|
||||
public function 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,
|
||||
$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('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('client.authentication.failed', $request));
|
||||
throw OAuthServerException::invalidClient();
|
||||
} elseif (
|
||||
is_array($client->getRedirectUri())
|
||||
&& in_array($redirectUri, $client->getRedirectUri()) === false
|
||||
) {
|
||||
$this->getEmitter()->emit(new RequestEvent('client.authentication.failed', $request));
|
||||
throw OAuthServerException::invalidClient();
|
||||
}
|
||||
}
|
||||
|
||||
$scopes = $this->validateScopes(
|
||||
$this->getQueryStringParameter('scope', $request),
|
||||
is_array($client->getRedirectUri())
|
||||
? $client->getRedirectUri()[0]
|
||||
: $client->getRedirectUri()
|
||||
);
|
||||
|
||||
$stateParameter = $this->getQueryStringParameter('state', $request);
|
||||
|
||||
$authorizationRequest = new AuthorizationRequest();
|
||||
$authorizationRequest->setGrantTypeId($this->getIdentifier());
|
||||
$authorizationRequest->setClient($client);
|
||||
$authorizationRequest->setRedirectUri($redirectUri);
|
||||
$authorizationRequest->setState($stateParameter);
|
||||
$authorizationRequest->setScopes($scopes);
|
||||
|
||||
return $authorizationRequest;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function completeAuthorizationRequest(AuthorizationRequest $authorizationRequest)
|
||||
{
|
||||
if ($authorizationRequest->getUser() instanceof UserEntityInterface === false) {
|
||||
throw new \LogicException('An instance of UserEntityInterface should be set on the AuthorizationRequest');
|
||||
}
|
||||
|
||||
$finalRedirectUri = ($authorizationRequest->getRedirectUri() === null)
|
||||
? is_array($authorizationRequest->getClient()->getRedirectUri())
|
||||
? $authorizationRequest->getClient()->getRedirectUri()[0]
|
||||
: $authorizationRequest->getClient()->getRedirectUri()
|
||||
: $authorizationRequest->getRedirectUri();
|
||||
|
||||
// The user approved the client, redirect them back with an access token
|
||||
if ($authorizationRequest->isAuthorizationApproved() === true) {
|
||||
$accessToken = $this->issueAccessToken(
|
||||
$this->accessTokenTTL,
|
||||
$authorizationRequest->getClient(),
|
||||
$authorizationRequest->getUser()->getIdentifier(),
|
||||
$authorizationRequest->getScopes()
|
||||
);
|
||||
|
||||
$response = new RedirectResponse();
|
||||
$response->setRedirectUri(
|
||||
$this->makeRedirectUri(
|
||||
$finalRedirectUri,
|
||||
[
|
||||
'access_token' => (string) $accessToken->convertToJWT($this->privateKey),
|
||||
'token_type' => 'bearer',
|
||||
'expires_in' => $accessToken->getExpiryDateTime()->getTimestamp() - (new \DateTime())->getTimestamp(),
|
||||
'state' => $authorizationRequest->getState(),
|
||||
],
|
||||
'#'
|
||||
)
|
||||
);
|
||||
|
||||
return $response;
|
||||
}
|
||||
|
||||
// The user denied the client, redirect them back with an error
|
||||
throw OAuthServerException::accessDenied(
|
||||
'The user denied the request',
|
||||
$finalRedirectUri
|
||||
);
|
||||
}
|
||||
}
|
110
src/Grant/PasswordGrant.php
Normal file
110
src/Grant/PasswordGrant.php
Normal file
@@ -0,0 +1,110 @@
|
||||
<?php
|
||||
/**
|
||||
* OAuth 2.0 Password grant.
|
||||
*
|
||||
* @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\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;
|
||||
use League\OAuth2\Server\RequestEvent;
|
||||
use League\OAuth2\Server\ResponseTypes\ResponseTypeInterface;
|
||||
use Psr\Http\Message\ServerRequestInterface;
|
||||
|
||||
/**
|
||||
* Password grant class.
|
||||
*/
|
||||
class PasswordGrant extends AbstractGrant
|
||||
{
|
||||
/**
|
||||
* @param \League\OAuth2\Server\Repositories\UserRepositoryInterface $userRepository
|
||||
* @param \League\OAuth2\Server\Repositories\RefreshTokenRepositoryInterface $refreshTokenRepository
|
||||
*/
|
||||
public function __construct(
|
||||
UserRepositoryInterface $userRepository,
|
||||
RefreshTokenRepositoryInterface $refreshTokenRepository
|
||||
) {
|
||||
$this->setUserRepository($userRepository);
|
||||
$this->setRefreshTokenRepository($refreshTokenRepository);
|
||||
|
||||
$this->refreshTokenTTL = new \DateInterval('P1M');
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function respondToAccessTokenRequest(
|
||||
ServerRequestInterface $request,
|
||||
ResponseTypeInterface $responseType,
|
||||
\DateInterval $accessTokenTTL
|
||||
) {
|
||||
// Validate request
|
||||
$client = $this->validateClient($request);
|
||||
$scopes = $this->validateScopes($this->getRequestParameter('scope', $request));
|
||||
$user = $this->validateUser($request, $client);
|
||||
|
||||
// Finalize the requested scopes
|
||||
$scopes = $this->scopeRepository->finalizeScopes($scopes, $this->getIdentifier(), $client, $user->getIdentifier());
|
||||
|
||||
// Issue and persist new tokens
|
||||
$accessToken = $this->issueAccessToken($accessTokenTTL, $client, $user->getIdentifier(), $scopes);
|
||||
$refreshToken = $this->issueRefreshToken($accessToken);
|
||||
|
||||
// Inject tokens into response
|
||||
$responseType->setAccessToken($accessToken);
|
||||
$responseType->setRefreshToken($refreshToken);
|
||||
|
||||
return $responseType;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \Psr\Http\Message\ServerRequestInterface $request
|
||||
* @param \League\OAuth2\Server\Entities\ClientEntityInterface $client
|
||||
*
|
||||
* @throws \League\OAuth2\Server\Exception\OAuthServerException
|
||||
*
|
||||
* @return \League\OAuth2\Server\Entities\UserEntityInterface
|
||||
*/
|
||||
protected function validateUser(ServerRequestInterface $request, ClientEntityInterface $client)
|
||||
{
|
||||
$username = $this->getRequestParameter('username', $request);
|
||||
if (is_null($username)) {
|
||||
throw OAuthServerException::invalidRequest('username', '`%s` parameter is missing');
|
||||
}
|
||||
|
||||
$password = $this->getRequestParameter('password', $request);
|
||||
if (is_null($password)) {
|
||||
throw OAuthServerException::invalidRequest('password', '`%s` parameter is missing');
|
||||
}
|
||||
|
||||
$user = $this->userRepository->getUserEntityByUserCredentials(
|
||||
$username,
|
||||
$password,
|
||||
$this->getIdentifier(),
|
||||
$client
|
||||
);
|
||||
if (!$user instanceof UserEntityInterface) {
|
||||
$this->getEmitter()->emit(new RequestEvent('user.authentication.failed', $request));
|
||||
|
||||
throw OAuthServerException::invalidCredentials();
|
||||
}
|
||||
|
||||
return $user;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getIdentifier()
|
||||
{
|
||||
return 'password';
|
||||
}
|
||||
}
|
132
src/Grant/RefreshTokenGrant.php
Normal file
132
src/Grant/RefreshTokenGrant.php
Normal file
@@ -0,0 +1,132 @@
|
||||
<?php
|
||||
/**
|
||||
* OAuth 2.0 Refresh token grant.
|
||||
*
|
||||
* @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\ScopeEntityInterface;
|
||||
use League\OAuth2\Server\Exception\OAuthServerException;
|
||||
use League\OAuth2\Server\Repositories\RefreshTokenRepositoryInterface;
|
||||
use League\OAuth2\Server\RequestEvent;
|
||||
use League\OAuth2\Server\ResponseTypes\ResponseTypeInterface;
|
||||
use Psr\Http\Message\ServerRequestInterface;
|
||||
|
||||
/**
|
||||
* Refresh token grant.
|
||||
*/
|
||||
class RefreshTokenGrant extends AbstractGrant
|
||||
{
|
||||
/**
|
||||
* @param \League\OAuth2\Server\Repositories\RefreshTokenRepositoryInterface $refreshTokenRepository
|
||||
*/
|
||||
public function __construct(RefreshTokenRepositoryInterface $refreshTokenRepository)
|
||||
{
|
||||
$this->setRefreshTokenRepository($refreshTokenRepository);
|
||||
|
||||
$this->refreshTokenTTL = new \DateInterval('P1M');
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function respondToAccessTokenRequest(
|
||||
ServerRequestInterface $request,
|
||||
ResponseTypeInterface $responseType,
|
||||
\DateInterval $accessTokenTTL
|
||||
) {
|
||||
// Validate request
|
||||
$client = $this->validateClient($request);
|
||||
$oldRefreshToken = $this->validateOldRefreshToken($request, $client->getIdentifier());
|
||||
$scopes = $this->validateScopes($this->getRequestParameter('scope', $request));
|
||||
|
||||
// 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 instanceof ScopeEntityInterface) {
|
||||
// @codeCoverageIgnoreStart
|
||||
throw OAuthServerException::invalidScope($scopeId);
|
||||
// @codeCoverageIgnoreEnd
|
||||
}
|
||||
|
||||
return $scope;
|
||||
}, $oldRefreshToken['scopes']);
|
||||
} else {
|
||||
// The OAuth spec says that a refreshed access token can have the original scopes or fewer so ensure
|
||||
// the request doesn't include any new scopes
|
||||
foreach ($scopes as $scope) {
|
||||
if (in_array($scope->getIdentifier(), $oldRefreshToken['scopes']) === false) {
|
||||
throw OAuthServerException::invalidScope($scope->getIdentifier());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Expire old tokens
|
||||
$this->accessTokenRepository->revokeAccessToken($oldRefreshToken['access_token_id']);
|
||||
$this->refreshTokenRepository->revokeRefreshToken($oldRefreshToken['refresh_token_id']);
|
||||
|
||||
// Issue and persist new tokens
|
||||
$accessToken = $this->issueAccessToken($accessTokenTTL, $client, $oldRefreshToken['user_id'], $scopes);
|
||||
$refreshToken = $this->issueRefreshToken($accessToken);
|
||||
|
||||
// Inject tokens into response
|
||||
$responseType->setAccessToken($accessToken);
|
||||
$responseType->setRefreshToken($refreshToken);
|
||||
|
||||
return $responseType;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \Psr\Http\Message\ServerRequestInterface $request
|
||||
* @param string $clientId
|
||||
*
|
||||
* @throws \League\OAuth2\Server\Exception\OAuthServerException
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function validateOldRefreshToken(ServerRequestInterface $request, $clientId)
|
||||
{
|
||||
$encryptedRefreshToken = $this->getRequestParameter('refresh_token', $request);
|
||||
if (is_null($encryptedRefreshToken)) {
|
||||
throw OAuthServerException::invalidRequest('refresh_token');
|
||||
}
|
||||
|
||||
// Validate refresh token
|
||||
try {
|
||||
$refreshToken = $this->decrypt($encryptedRefreshToken);
|
||||
} catch (\LogicException $e) {
|
||||
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');
|
||||
}
|
||||
|
||||
if ($refreshTokenData['expire_time'] < time()) {
|
||||
throw OAuthServerException::invalidRefreshToken('Token has expired');
|
||||
}
|
||||
|
||||
if ($this->refreshTokenRepository->isRefreshTokenRevoked($refreshTokenData['refresh_token_id']) === true) {
|
||||
throw OAuthServerException::invalidRefreshToken('Token has been revoked');
|
||||
}
|
||||
|
||||
return $refreshTokenData;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getIdentifier()
|
||||
{
|
||||
return 'refresh_token';
|
||||
}
|
||||
}
|
@@ -1,466 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* OAuth 2.0 Authorization Server
|
||||
*
|
||||
* @package php-loep/oauth2-server
|
||||
* @author Alex Bilbie <hello@alexbilbie.com>
|
||||
* @copyright Copyright (c) 2013 PHP League of Extraordinary Packages
|
||||
* @license http://mit-license.org/
|
||||
* @link http://github.com/php-loep/oauth2-server
|
||||
*/
|
||||
|
||||
namespace League\OAuth2\Server;
|
||||
|
||||
use League\OAuth2\Server\Util\Request;
|
||||
use League\OAuth2\Server\Util\SecureKey;
|
||||
use League\OAuth2\Server\Storage\SessionInterface;
|
||||
use League\OAuth2\Server\Storage\ClientInterface;
|
||||
use League\OAuth2\Server\Storage\ScopeInterface;
|
||||
use League\OAuth2\Server\Grant\GrantTypeInterface;
|
||||
|
||||
/**
|
||||
* OAuth 2.0 authorization server class
|
||||
*/
|
||||
class Authorization
|
||||
{
|
||||
/**
|
||||
* The delimeter between scopes specified in the scope query string parameter
|
||||
*
|
||||
* The OAuth 2 specification states it should be a space but most use a comma
|
||||
* @var string
|
||||
*/
|
||||
protected $scopeDelimeter = ' ';
|
||||
|
||||
/**
|
||||
* The TTL (time to live) of an access token in seconds (default: 3600)
|
||||
* @var integer
|
||||
*/
|
||||
protected $accessTokenTTL = 3600;
|
||||
|
||||
/**
|
||||
* The registered grant response types
|
||||
* @var array
|
||||
*/
|
||||
protected $responseTypes = array();
|
||||
|
||||
/**
|
||||
* The client, scope and session storage classes
|
||||
* @var array
|
||||
*/
|
||||
protected $storages = array();
|
||||
|
||||
/**
|
||||
* The registered grant types
|
||||
* @var array
|
||||
*/
|
||||
protected $grantTypes = array();
|
||||
|
||||
/**
|
||||
* Require the "scope" parameter to be in checkAuthoriseParams()
|
||||
* @var boolean
|
||||
*/
|
||||
protected $requireScopeParam = true;
|
||||
|
||||
/**
|
||||
* Default scope to be used if none is provided and requireScopeParam is false
|
||||
* @var string
|
||||
*/
|
||||
protected $defaultScope = null;
|
||||
|
||||
/**
|
||||
* Require the "state" parameter to be in checkAuthoriseParams()
|
||||
* @var boolean
|
||||
*/
|
||||
protected $requireStateParam = false;
|
||||
|
||||
/**
|
||||
* The request object
|
||||
* @var Util\RequestInterface
|
||||
*/
|
||||
protected $request = null;
|
||||
|
||||
/**
|
||||
* Exception error codes
|
||||
* @var array
|
||||
*/
|
||||
protected static $exceptionCodes = array(
|
||||
0 => 'invalid_request',
|
||||
1 => 'unauthorized_client',
|
||||
2 => 'access_denied',
|
||||
3 => 'unsupported_response_type',
|
||||
4 => 'invalid_scope',
|
||||
5 => 'server_error',
|
||||
6 => 'temporarily_unavailable',
|
||||
7 => 'unsupported_grant_type',
|
||||
8 => 'invalid_client',
|
||||
9 => 'invalid_grant'
|
||||
);
|
||||
|
||||
/**
|
||||
* Exception error messages
|
||||
* @var array
|
||||
*/
|
||||
protected static $exceptionMessages = array(
|
||||
'invalid_request' => 'The request is missing a required parameter, includes an invalid parameter value, includes a parameter more than once, or is otherwise malformed. Check the "%s" parameter.',
|
||||
'unauthorized_client' => 'The client is not authorized to request an access token using this method.',
|
||||
'access_denied' => 'The resource owner or authorization server denied the request.',
|
||||
'unsupported_response_type' => 'The authorization server does not support obtaining an access token using this method.',
|
||||
'invalid_scope' => 'The requested scope is invalid, unknown, or malformed. Check the "%s" scope.',
|
||||
'server_error' => 'The authorization server encountered an unexpected condition which prevented it from fulfilling the request.',
|
||||
'temporarily_unavailable' => 'The authorization server is currently unable to handle the request due to a temporary overloading or maintenance of the server.',
|
||||
'unsupported_grant_type' => 'The authorization grant type "%s" is not supported by the authorization server',
|
||||
'invalid_client' => 'Client authentication failed',
|
||||
'invalid_grant' => 'The provided authorization grant is invalid, expired, revoked, does not match the redirection URI used in the authorization request, or was issued to another client. Check the "%s" parameter.',
|
||||
'invalid_credentials' => 'The user credentials were incorrect.',
|
||||
'invalid_refresh' => 'The refresh token is invalid.',
|
||||
);
|
||||
|
||||
/**
|
||||
* Exception error HTTP status codes
|
||||
* @var array
|
||||
*
|
||||
* RFC 6749, section 4.1.2.1.:
|
||||
* No 503 status code for 'temporarily_unavailable', because
|
||||
* "a 503 Service Unavailable HTTP status code cannot be
|
||||
* returned to the client via an HTTP redirect"
|
||||
*/
|
||||
protected static $exceptionHttpStatusCodes = array(
|
||||
'invalid_request' => 400,
|
||||
'unauthorized_client' => 400,
|
||||
'access_denied' => 401,
|
||||
'unsupported_response_type' => 400,
|
||||
'invalid_scope' => 400,
|
||||
'server_error' => 500,
|
||||
'temporarily_unavailable' => 400,
|
||||
'unsupported_grant_type' => 501,
|
||||
'invalid_client' => 401,
|
||||
'invalid_grant' => 400,
|
||||
'invalid_credentials' => 400,
|
||||
'invalid_refresh' => 400,
|
||||
);
|
||||
|
||||
/**
|
||||
* Get all headers that have to be send with the error response
|
||||
*
|
||||
* @param string $error The error message key
|
||||
* @return array Array with header values
|
||||
*/
|
||||
public static function getExceptionHttpHeaders($error)
|
||||
{
|
||||
$headers = array();
|
||||
switch (self::$exceptionHttpStatusCodes[$error]) {
|
||||
case 401:
|
||||
$headers[] = 'HTTP/1.1 401 Unauthorized';
|
||||
break;
|
||||
case 500:
|
||||
$headers[] = 'HTTP/1.1 500 Internal Server Error';
|
||||
break;
|
||||
case 501:
|
||||
$headers[] = 'HTTP/1.1 501 Not Implemented';
|
||||
break;
|
||||
case 400:
|
||||
default:
|
||||
$headers[] = 'HTTP/1.1 400 Bad Request';
|
||||
}
|
||||
|
||||
// Add "WWW-Authenticate" header
|
||||
//
|
||||
// RFC 6749, section 5.2.:
|
||||
// "If the client attempted to authenticate via the 'Authorization'
|
||||
// request header field, the authorization server MUST
|
||||
// respond with an HTTP 401 (Unauthorized) status code and
|
||||
// include the "WWW-Authenticate" response header field
|
||||
// matching the authentication scheme used by the client.
|
||||
// @codeCoverageIgnoreStart
|
||||
if ($error === 'invalid_client') {
|
||||
$authScheme = null;
|
||||
$request = new Request();
|
||||
if ($request->server('PHP_AUTH_USER') !== null) {
|
||||
$authScheme = 'Basic';
|
||||
} else {
|
||||
$authHeader = $request->header('Authorization');
|
||||
if ($authHeader !== null) {
|
||||
if (strpos($authHeader, 'Bearer') === 0) {
|
||||
$authScheme = 'Bearer';
|
||||
} elseif (strpos($authHeader, 'Basic') === 0) {
|
||||
$authScheme = 'Basic';
|
||||
}
|
||||
}
|
||||
}
|
||||
if ($authScheme !== null) {
|
||||
$headers[] = 'WWW-Authenticate: '.$authScheme.' realm=""';
|
||||
}
|
||||
}
|
||||
// @codeCoverageIgnoreEnd
|
||||
|
||||
return $headers;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an exception message
|
||||
*
|
||||
* @param string $error The error message key
|
||||
* @return string The error message
|
||||
*/
|
||||
public static function getExceptionMessage($error = '')
|
||||
{
|
||||
return self::$exceptionMessages[$error];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an exception code
|
||||
*
|
||||
* @param integer $code The exception code
|
||||
* @return string The exception code type
|
||||
*/
|
||||
public static function getExceptionType($code = 0)
|
||||
{
|
||||
return self::$exceptionCodes[$code];
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new OAuth2 authorization server
|
||||
*
|
||||
* @param ClientInterface $client A class which inherits from Storage/ClientInterface
|
||||
* @param SessionInterface $session A class which inherits from Storage/SessionInterface
|
||||
* @param ScopeInterface $scope A class which inherits from Storage/ScopeInterface
|
||||
*/
|
||||
public function __construct(ClientInterface $client, SessionInterface $session, ScopeInterface $scope)
|
||||
{
|
||||
$this->storages = array(
|
||||
'client' => $client,
|
||||
'session' => $session,
|
||||
'scope' => $scope
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable support for a grant
|
||||
* @param GrantTypeInterface $grantType A grant class which conforms to Interface/GrantTypeInterface
|
||||
* @param null|string $identifier An identifier for the grant (autodetected if not passed)
|
||||
*/
|
||||
public function addGrantType(GrantTypeInterface $grantType, $identifier = null)
|
||||
{
|
||||
if (is_null($identifier)) {
|
||||
$identifier = $grantType->getIdentifier();
|
||||
}
|
||||
$this->grantTypes[$identifier] = $grantType;
|
||||
|
||||
if ( ! is_null($grantType->getResponseType())) {
|
||||
$this->responseTypes[] = $grantType->getResponseType();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a grant type has been enabled
|
||||
* @param string $identifier The grant type identifier
|
||||
* @return boolean Returns "true" if enabled, "false" if not
|
||||
*/
|
||||
public function hasGrantType($identifier)
|
||||
{
|
||||
return (array_key_exists($identifier, $this->grantTypes));
|
||||
}
|
||||
|
||||
public function getResponseTypes()
|
||||
{
|
||||
return $this->responseTypes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Require the "scope" paremter in checkAuthoriseParams()
|
||||
* @param boolean $require
|
||||
* @return void
|
||||
*/
|
||||
public function requireScopeParam($require = true)
|
||||
{
|
||||
$this->requireScopeParam = $require;
|
||||
}
|
||||
|
||||
/**
|
||||
* Is the scope parameter required?
|
||||
* @return bool
|
||||
*/
|
||||
public function scopeParamRequired()
|
||||
{
|
||||
return $this->requireScopeParam;
|
||||
}
|
||||
|
||||
/**
|
||||
* Default scope to be used if none is provided and requireScopeParam is false
|
||||
* @var string
|
||||
*/
|
||||
public function setDefaultScope($default = null)
|
||||
{
|
||||
$this->defaultScope = $default;
|
||||
}
|
||||
|
||||
/**
|
||||
* Default scope to be used if none is provided and requireScopeParam is false
|
||||
* @return string|null
|
||||
*/
|
||||
public function getDefaultScope()
|
||||
{
|
||||
return $this->defaultScope;
|
||||
}
|
||||
|
||||
/**
|
||||
* Require the "state" paremter in checkAuthoriseParams()
|
||||
* @param boolean $require
|
||||
* @return void
|
||||
*/
|
||||
public function stateParamRequired()
|
||||
{
|
||||
return $this->requireStateParam;
|
||||
}
|
||||
|
||||
/**
|
||||
* Require the "state" paremter in checkAuthoriseParams()
|
||||
* @param boolean $require
|
||||
* @return void
|
||||
*/
|
||||
public function requireStateParam($require = false)
|
||||
{
|
||||
$this->requireStateParam = $require;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the scope delimeter
|
||||
*
|
||||
* @return string The scope delimiter (default: ",")
|
||||
*/
|
||||
public function getScopeDelimeter()
|
||||
{
|
||||
return $this->scopeDelimeter;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the scope delimiter
|
||||
*
|
||||
* @param string $scopeDelimeter
|
||||
*/
|
||||
public function setScopeDelimeter($scopeDelimeter = ' ')
|
||||
{
|
||||
$this->scopeDelimeter = $scopeDelimeter;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the TTL for an access token
|
||||
* @return int The TTL
|
||||
*/
|
||||
public function getAccessTokenTTL()
|
||||
{
|
||||
return $this->accessTokenTTL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the TTL for an access token
|
||||
* @param int $accessTokenTTL The new TTL
|
||||
*/
|
||||
public function setAccessTokenTTL($accessTokenTTL = 3600)
|
||||
{
|
||||
$this->accessTokenTTL = $accessTokenTTL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the Request Object
|
||||
*
|
||||
* @param Util\RequestInterface The Request Object
|
||||
*/
|
||||
public function setRequest(Util\RequestInterface $request)
|
||||
{
|
||||
$this->request = $request;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the Request object. It will create one from the globals if one is not set.
|
||||
*
|
||||
* @return Util\RequestInterface
|
||||
*/
|
||||
public function getRequest()
|
||||
{
|
||||
if ($this->request === null) {
|
||||
// @codeCoverageIgnoreStart
|
||||
$this->request = Request::buildFromGlobals();
|
||||
|
||||
}
|
||||
// @codeCoverageIgnoreEnd
|
||||
|
||||
return $this->request;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a storage class
|
||||
* @param string $obj The class required
|
||||
* @return Storage\ClientInterface|Storage\ScopeInterface|Storage\SessionInterface
|
||||
*/
|
||||
public function getStorage($obj)
|
||||
{
|
||||
return $this->storages[$obj];
|
||||
}
|
||||
|
||||
/**
|
||||
* Issue an access token
|
||||
*
|
||||
* @param array $inputParams Optional array of parsed $_POST keys
|
||||
* @return array Authorise request parameters
|
||||
*/
|
||||
public function issueAccessToken($inputParams = array())
|
||||
{
|
||||
$grantType = $this->getParam('grant_type', 'post', $inputParams);
|
||||
|
||||
if (is_null($grantType)) {
|
||||
throw new Exception\ClientException(sprintf(self::$exceptionMessages['invalid_request'], 'grant_type'), 0);
|
||||
}
|
||||
|
||||
// Ensure grant type is one that is recognised and is enabled
|
||||
if ( ! in_array($grantType, array_keys($this->grantTypes))) {
|
||||
throw new Exception\ClientException(sprintf(self::$exceptionMessages['unsupported_grant_type'], $grantType), 7);
|
||||
}
|
||||
|
||||
// Complete the flow
|
||||
return $this->getGrantType($grantType)->completeFlow($inputParams);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a grant type class
|
||||
* @param string $grantType The grant type identifer
|
||||
* @return Grant\AuthCode|Grant\ClientCredentials|Grant\Implict|Grant\Password|Grant\RefreshToken
|
||||
*/
|
||||
public function getGrantType($grantType)
|
||||
{
|
||||
if (isset($this->grantTypes[$grantType])) {
|
||||
return $this->grantTypes[$grantType];
|
||||
}
|
||||
|
||||
throw new Exception\InvalidGrantTypeException(sprintf(self::$exceptionMessages['unsupported_grant_type'], $grantType), 9);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a parameter from passed input parameters or the Request class
|
||||
* @param string|array $param Required parameter
|
||||
* @param string $method Get/put/post/delete
|
||||
* @param array $inputParams Passed input parameters
|
||||
* @return mixed 'Null' if parameter is missing
|
||||
*/
|
||||
public function getParam($param = '', $method = 'get', $inputParams = array(), $default = null)
|
||||
{
|
||||
if (is_string($param)) {
|
||||
if (isset($inputParams[$param])) {
|
||||
return $inputParams[$param];
|
||||
} elseif ($param === 'client_id' && ! is_null($clientId = $this->getRequest()->server('PHP_AUTH_USER'))) {
|
||||
return $clientId;
|
||||
} elseif ($param === 'client_secret' && ! is_null($clientSecret = $this->getRequest()->server('PHP_AUTH_PW'))) {
|
||||
return $clientSecret;
|
||||
} else {
|
||||
return $this->getRequest()->{$method}($param, $default);
|
||||
}
|
||||
} else {
|
||||
$response = array();
|
||||
foreach ($param as $p) {
|
||||
$response[$p] = $this->getParam($p, $method, $inputParams);
|
||||
}
|
||||
return $response;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@@ -1,20 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* OAuth 2.0 Client Exception
|
||||
*
|
||||
* @package php-loep/oauth2-server
|
||||
* @author Alex Bilbie <hello@alexbilbie.com>
|
||||
* @copyright Copyright (c) 2013 PHP League of Extraordinary Packages
|
||||
* @license http://mit-license.org/
|
||||
* @link http://github.com/php-loep/oauth2-server
|
||||
*/
|
||||
|
||||
namespace League\OAuth2\Server\Exception;
|
||||
|
||||
/**
|
||||
* ClientException Exception
|
||||
*/
|
||||
class ClientException extends OAuth2Exception
|
||||
{
|
||||
|
||||
}
|
@@ -1,20 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* OAuth 2.0 Invalid Access Token Exception
|
||||
*
|
||||
* @package php-loep/oauth2-server
|
||||
* @author Alex Bilbie <hello@alexbilbie.com>
|
||||
* @copyright Copyright (c) 2013 PHP League of Extraordinary Packages
|
||||
* @license http://mit-license.org/
|
||||
* @link http://github.com/php-loep/oauth2-server
|
||||
*/
|
||||
|
||||
namespace League\OAuth2\Server\Exception;
|
||||
|
||||
/**
|
||||
* InvalidAccessToken Exception
|
||||
*/
|
||||
class InvalidAccessTokenException extends OAuth2Exception
|
||||
{
|
||||
|
||||
}
|
@@ -1,20 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* OAuth 2.0 Invalid Grant Type Exception
|
||||
*
|
||||
* @package php-loep/oauth2-server
|
||||
* @author Alex Bilbie <hello@alexbilbie.com>
|
||||
* @copyright Copyright (c) 2013 PHP League of Extraordinary Packages
|
||||
* @license http://mit-license.org/
|
||||
* @link http://github.com/php-loep/oauth2-server
|
||||
*/
|
||||
|
||||
namespace League\OAuth2\Server\Exception;
|
||||
|
||||
/**
|
||||
* InvalidGrantTypeException Exception
|
||||
*/
|
||||
class InvalidGrantTypeException extends OAuth2Exception
|
||||
{
|
||||
|
||||
}
|
@@ -1,20 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* OAuth 2.0 Base Exception
|
||||
*
|
||||
* @package php-loep/oauth2-server
|
||||
* @author Alex Bilbie <hello@alexbilbie.com>
|
||||
* @copyright Copyright (c) 2013 PHP League of Extraordinary Packages
|
||||
* @license http://mit-license.org/
|
||||
* @link http://github.com/php-loep/oauth2-server
|
||||
*/
|
||||
|
||||
namespace League\OAuth2\Server\Exception;
|
||||
|
||||
/**
|
||||
* Exception class
|
||||
*/
|
||||
class OAuth2Exception extends \Exception
|
||||
{
|
||||
|
||||
}
|
@@ -1,293 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* OAuth 2.0 Auth code grant
|
||||
*
|
||||
* @package php-loep/oauth2-server
|
||||
* @author Alex Bilbie <hello@alexbilbie.com>
|
||||
* @copyright Copyright (c) 2013 PHP League of Extraordinary Packages
|
||||
* @license http://mit-license.org/
|
||||
* @link http://github.com/php-loep/oauth2-server
|
||||
*/
|
||||
|
||||
namespace League\OAuth2\Server\Grant;
|
||||
|
||||
use League\OAuth2\Server\Request;
|
||||
use League\OAuth2\Server\Authorization;
|
||||
use League\OAuth2\Server\Exception;
|
||||
use League\OAuth2\Server\Util\SecureKey;
|
||||
use League\OAuth2\Server\Storage\SessionInterface;
|
||||
use League\OAuth2\Server\Storage\ClientInterface;
|
||||
use League\OAuth2\Server\Storage\ScopeInterface;
|
||||
|
||||
/**
|
||||
* Auth code grant class
|
||||
*/
|
||||
class AuthCode implements GrantTypeInterface {
|
||||
|
||||
/**
|
||||
* Grant identifier
|
||||
* @var string
|
||||
*/
|
||||
protected $identifier = 'authorization_code';
|
||||
|
||||
/**
|
||||
* Response type
|
||||
* @var string
|
||||
*/
|
||||
protected $responseType = 'code';
|
||||
|
||||
/**
|
||||
* AuthServer instance
|
||||
* @var AuthServer
|
||||
*/
|
||||
protected $authServer = null;
|
||||
|
||||
/**
|
||||
* Access token expires in override
|
||||
* @var int
|
||||
*/
|
||||
protected $accessTokenTTL = null;
|
||||
|
||||
/**
|
||||
* The TTL of the auth token
|
||||
* @var integer
|
||||
*/
|
||||
protected $authTokenTTL = 600;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
* @param Authorization $authServer Authorization server instance
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(Authorization $authServer)
|
||||
{
|
||||
$this->authServer = $authServer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the identifier
|
||||
* @return string
|
||||
*/
|
||||
public function getIdentifier()
|
||||
{
|
||||
return $this->identifier;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the response type
|
||||
* @return string
|
||||
*/
|
||||
public function getResponseType()
|
||||
{
|
||||
return $this->responseType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Override the default access token expire time
|
||||
* @param int $accessTokenTTL
|
||||
* @return void
|
||||
*/
|
||||
public function setAccessTokenTTL($accessTokenTTL)
|
||||
{
|
||||
$this->accessTokenTTL = $accessTokenTTL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Override the default access token expire time
|
||||
* @param int $authTokenTTL
|
||||
* @return void
|
||||
*/
|
||||
public function setAuthTokenTTL($authTokenTTL)
|
||||
{
|
||||
$this->authTokenTTL = $authTokenTTL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check authorise parameters
|
||||
*
|
||||
* @param array $inputParams Optional array of parsed $_GET keys
|
||||
* @throws \OAuth2\Exception\ClientException
|
||||
* @return array Authorise request parameters
|
||||
*/
|
||||
public function checkAuthoriseParams($inputParams = array())
|
||||
{
|
||||
// Auth params
|
||||
$authParams = $this->authServer->getParam(array('client_id', 'redirect_uri', 'response_type', 'scope', 'state'), 'get', $inputParams);
|
||||
|
||||
if (is_null($authParams['client_id'])) {
|
||||
throw new Exception\ClientException(sprintf($this->authServer->getExceptionMessage('invalid_request'), 'client_id'), 0);
|
||||
}
|
||||
|
||||
if (is_null($authParams['redirect_uri'])) {
|
||||
throw new Exception\ClientException(sprintf($this->authServer->getExceptionMessage('invalid_request'), 'redirect_uri'), 0);
|
||||
}
|
||||
|
||||
if ($this->authServer->stateParamRequired() === true && is_null($authParams['state'])) {
|
||||
throw new Exception\ClientException(sprintf($this->authServer->getExceptionMessage('invalid_request'), 'state'), 0);
|
||||
}
|
||||
|
||||
// Validate client ID and redirect URI
|
||||
$clientDetails = $this->authServer->getStorage('client')->getClient($authParams['client_id'], null, $authParams['redirect_uri'], $this->identifier);
|
||||
|
||||
if ($clientDetails === false) {
|
||||
throw new Exception\ClientException($this->authServer->getExceptionMessage('invalid_client'), 8);
|
||||
}
|
||||
|
||||
$authParams['client_details'] = $clientDetails;
|
||||
|
||||
if (is_null($authParams['response_type'])) {
|
||||
throw new Exception\ClientException(sprintf($this->authServer->getExceptionMessage('invalid_request'), 'response_type'), 0);
|
||||
}
|
||||
|
||||
// Ensure response type is one that is recognised
|
||||
if ( ! in_array($authParams['response_type'], $this->authServer->getResponseTypes())) {
|
||||
throw new Exception\ClientException($this->authServer->getExceptionMessage('unsupported_response_type'), 3);
|
||||
}
|
||||
|
||||
// Validate scopes
|
||||
$scopes = explode($this->authServer->getScopeDelimeter(), $authParams['scope']);
|
||||
|
||||
for ($i = 0; $i < count($scopes); $i++) {
|
||||
$scopes[$i] = trim($scopes[$i]);
|
||||
if ($scopes[$i] === '') unset($scopes[$i]); // Remove any junk scopes
|
||||
}
|
||||
|
||||
if ($this->authServer->scopeParamRequired() === true && count($scopes) === 0) {
|
||||
throw new Exception\ClientException(sprintf($this->authServer->getExceptionMessage('invalid_request'), 'scope'), 0);
|
||||
} elseif (count($scopes) === 0 && $this->authServer->getDefaultScope()) {
|
||||
$scopes = array($this->authServer->getDefaultScope());
|
||||
}
|
||||
|
||||
$authParams['scopes'] = array();
|
||||
|
||||
foreach ($scopes as $scope) {
|
||||
$scopeDetails = $this->authServer->getStorage('scope')->getScope($scope, $authParams['client_id'], $this->identifier);
|
||||
|
||||
if ($scopeDetails === false) {
|
||||
throw new Exception\ClientException(sprintf($this->authServer->getExceptionMessage('invalid_scope'), $scope), 4);
|
||||
}
|
||||
|
||||
$authParams['scopes'][] = $scopeDetails;
|
||||
}
|
||||
|
||||
return $authParams;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse a new authorise request
|
||||
*
|
||||
* @param string $type The session owner's type
|
||||
* @param string $typeId The session owner's ID
|
||||
* @param array $authParams The authorise request $_GET parameters
|
||||
* @return string An authorisation code
|
||||
*/
|
||||
public function newAuthoriseRequest($type, $typeId, $authParams = array())
|
||||
{
|
||||
// Generate an auth code
|
||||
$authCode = SecureKey::make();
|
||||
|
||||
// Remove any old sessions the user might have
|
||||
$this->authServer->getStorage('session')->deleteSession($authParams['client_id'], $type, $typeId);
|
||||
|
||||
// List of scopes IDs
|
||||
$scopeIds = array();
|
||||
foreach ($authParams['scopes'] as $scope)
|
||||
{
|
||||
$scopeIds[] = $scope['id'];
|
||||
}
|
||||
|
||||
// Create a new session
|
||||
$sessionId = $this->authServer->getStorage('session')->createSession($authParams['client_id'], $type, $typeId);
|
||||
|
||||
// Associate a redirect URI
|
||||
$this->authServer->getStorage('session')->associateRedirectUri($sessionId, $authParams['redirect_uri']);
|
||||
|
||||
// Associate the auth code
|
||||
$this->authServer->getStorage('session')->associateAuthCode($sessionId, $authCode, time() + $this->authTokenTTL, implode(',', $scopeIds));
|
||||
|
||||
return $authCode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Complete the auth code grant
|
||||
* @param null|array $inputParams
|
||||
* @return array
|
||||
*/
|
||||
public function completeFlow($inputParams = null)
|
||||
{
|
||||
// Get the required params
|
||||
$authParams = $this->authServer->getParam(array('client_id', 'client_secret', 'redirect_uri', 'code'), 'post', $inputParams);
|
||||
|
||||
if (is_null($authParams['client_id'])) {
|
||||
throw new Exception\ClientException(sprintf($this->authServer->getExceptionMessage('invalid_request'), 'client_id'), 0);
|
||||
}
|
||||
|
||||
if (is_null($authParams['client_secret'])) {
|
||||
throw new Exception\ClientException(sprintf($this->authServer->getExceptionMessage('invalid_request'), 'client_secret'), 0);
|
||||
}
|
||||
|
||||
if (is_null($authParams['redirect_uri'])) {
|
||||
throw new Exception\ClientException(sprintf($this->authServer->getExceptionMessage('invalid_request'), 'redirect_uri'), 0);
|
||||
}
|
||||
|
||||
// Validate client ID and redirect URI
|
||||
$clientDetails = $this->authServer->getStorage('client')->getClient($authParams['client_id'], $authParams['client_secret'], $authParams['redirect_uri'], $this->identifier);
|
||||
|
||||
if ($clientDetails === false) {
|
||||
throw new Exception\ClientException($this->authServer->getExceptionMessage('invalid_client'), 8);
|
||||
}
|
||||
|
||||
$authParams['client_details'] = $clientDetails;
|
||||
|
||||
// Validate the authorization code
|
||||
if (is_null($authParams['code'])) {
|
||||
throw new Exception\ClientException(sprintf($this->authServer->getExceptionMessage('invalid_request'), 'code'), 0);
|
||||
}
|
||||
|
||||
// Verify the authorization code matches the client_id and the request_uri
|
||||
$session = $this->authServer->getStorage('session')->validateAuthCode($authParams['client_id'], $authParams['redirect_uri'], $authParams['code']);
|
||||
|
||||
if ( ! $session) {
|
||||
throw new Exception\ClientException(sprintf($this->authServer->getExceptionMessage('invalid_grant'), 'code'), 9);
|
||||
}
|
||||
|
||||
// A session ID was returned so update it with an access token and remove the authorisation code
|
||||
|
||||
$accessToken = SecureKey::make();
|
||||
$accessTokenExpiresIn = ($this->accessTokenTTL !== null) ? $this->accessTokenTTL : $this->authServer->getAccessTokenTTL();
|
||||
$accessTokenExpires = time() + $accessTokenExpiresIn;
|
||||
|
||||
// Remove the auth code
|
||||
$this->authServer->getStorage('session')->removeAuthCode($session['id']);
|
||||
|
||||
// Create an access token
|
||||
$accessTokenId = $this->authServer->getStorage('session')->associateAccessToken($session['id'], $accessToken, $accessTokenExpires);
|
||||
|
||||
// Associate scopes with the access token
|
||||
if ( ! is_null($session['scope_ids'])) {
|
||||
$scopeIds = explode(',', $session['scope_ids']);
|
||||
|
||||
foreach ($scopeIds as $scopeId) {
|
||||
$this->authServer->getStorage('session')->associateScope($accessTokenId, $scopeId);
|
||||
}
|
||||
}
|
||||
|
||||
$response = array(
|
||||
'access_token' => $accessToken,
|
||||
'token_type' => 'bearer',
|
||||
'expires' => $accessTokenExpires,
|
||||
'expires_in' => $accessTokenExpiresIn
|
||||
);
|
||||
|
||||
// Associate a refresh token if set
|
||||
if ($this->authServer->hasGrantType('refresh_token')) {
|
||||
$refreshToken = SecureKey::make();
|
||||
$refreshTokenTTL = time() + $this->authServer->getGrantType('refresh_token')->getRefreshTokenTTL();
|
||||
$this->authServer->getStorage('session')->associateRefreshToken($accessTokenId, $refreshToken, $refreshTokenTTL);
|
||||
$response['refresh_token'] = $refreshToken;
|
||||
}
|
||||
|
||||
return $response;
|
||||
}
|
||||
|
||||
}
|
@@ -1,173 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* OAuth 2.0 Client credentials grant
|
||||
*
|
||||
* @package php-loep/oauth2-server
|
||||
* @author Alex Bilbie <hello@alexbilbie.com>
|
||||
* @copyright Copyright (c) 2013 PHP League of Extraordinary Packages
|
||||
* @license http://mit-license.org/
|
||||
* @link http://github.com/php-loep/oauth2-server
|
||||
*/
|
||||
|
||||
namespace League\OAuth2\Server\Grant;
|
||||
|
||||
use League\OAuth2\Server\Request;
|
||||
use League\OAuth2\Server\Authorization;
|
||||
use League\OAuth2\Server\Exception;
|
||||
use League\OAuth2\Server\Util\SecureKey;
|
||||
use League\OAuth2\Server\Storage\SessionInterface;
|
||||
use League\OAuth2\Server\Storage\ClientInterface;
|
||||
use League\OAuth2\Server\Storage\ScopeInterface;
|
||||
|
||||
/**
|
||||
* Client credentials grant class
|
||||
*/
|
||||
class ClientCredentials implements GrantTypeInterface {
|
||||
|
||||
/**
|
||||
* Grant identifier
|
||||
* @var string
|
||||
*/
|
||||
protected $identifier = 'client_credentials';
|
||||
|
||||
/**
|
||||
* Response type
|
||||
* @var string
|
||||
*/
|
||||
protected $responseType = null;
|
||||
|
||||
/**
|
||||
* AuthServer instance
|
||||
* @var AuthServer
|
||||
*/
|
||||
protected $authServer = null;
|
||||
|
||||
/**
|
||||
* Access token expires in override
|
||||
* @var int
|
||||
*/
|
||||
protected $accessTokenTTL = null;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
* @param Authorization $authServer Authorization server instance
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(Authorization $authServer)
|
||||
{
|
||||
$this->authServer = $authServer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the identifier
|
||||
* @return string
|
||||
*/
|
||||
public function getIdentifier()
|
||||
{
|
||||
return $this->identifier;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the response type
|
||||
* @return string
|
||||
*/
|
||||
public function getResponseType()
|
||||
{
|
||||
return $this->responseType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Override the default access token expire time
|
||||
* @param int $accessTokenTTL
|
||||
* @return void
|
||||
*/
|
||||
public function setAccessTokenTTL($accessTokenTTL)
|
||||
{
|
||||
$this->accessTokenTTL = $accessTokenTTL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Complete the client credentials grant
|
||||
* @param null|array $inputParams
|
||||
* @return array
|
||||
*/
|
||||
public function completeFlow($inputParams = null)
|
||||
{
|
||||
// Get the required params
|
||||
$authParams = $this->authServer->getParam(array('client_id', 'client_secret'), 'post', $inputParams);
|
||||
|
||||
if (is_null($authParams['client_id'])) {
|
||||
throw new Exception\ClientException(sprintf(Authorization::getExceptionMessage('invalid_request'), 'client_id'), 0);
|
||||
}
|
||||
|
||||
if (is_null($authParams['client_secret'])) {
|
||||
throw new Exception\ClientException(sprintf(Authorization::getExceptionMessage('invalid_request'), 'client_secret'), 0);
|
||||
}
|
||||
|
||||
// Validate client ID and client secret
|
||||
$clientDetails = $this->authServer->getStorage('client')->getClient($authParams['client_id'], $authParams['client_secret'], null, $this->identifier);
|
||||
|
||||
if ($clientDetails === false) {
|
||||
throw new Exception\ClientException(Authorization::getExceptionMessage('invalid_client'), 8);
|
||||
}
|
||||
|
||||
$authParams['client_details'] = $clientDetails;
|
||||
|
||||
// Validate any scopes that are in the request
|
||||
$scope = $this->authServer->getParam('scope', 'post', $inputParams, '');
|
||||
$scopes = explode($this->authServer->getScopeDelimeter(), $scope);
|
||||
|
||||
for ($i = 0; $i < count($scopes); $i++) {
|
||||
$scopes[$i] = trim($scopes[$i]);
|
||||
if ($scopes[$i] === '') unset($scopes[$i]); // Remove any junk scopes
|
||||
}
|
||||
|
||||
if ($this->authServer->scopeParamRequired() === true && count($scopes) === 0) {
|
||||
throw new Exception\ClientException(sprintf($this->authServer->getExceptionMessage('invalid_request'), 'scope'), 0);
|
||||
} elseif (count($scopes) === 0 && $this->authServer->getDefaultScope()) {
|
||||
$scopes = array($this->authServer->getDefaultScope());
|
||||
}
|
||||
|
||||
$authParams['scopes'] = array();
|
||||
|
||||
foreach ($scopes as $scope) {
|
||||
$scopeDetails = $this->authServer->getStorage('scope')->getScope($scope, $authParams['client_id'], $this->identifier);
|
||||
|
||||
if ($scopeDetails === false) {
|
||||
throw new Exception\ClientException(sprintf($this->authServer->getExceptionMessage('invalid_scope'), $scope), 4);
|
||||
}
|
||||
|
||||
$authParams['scopes'][] = $scopeDetails;
|
||||
}
|
||||
|
||||
// Generate an access token
|
||||
$accessToken = SecureKey::make();
|
||||
$accessTokenExpiresIn = ($this->accessTokenTTL !== null) ? $this->accessTokenTTL : $this->authServer->getAccessTokenTTL();
|
||||
$accessTokenExpires = time() + $accessTokenExpiresIn;
|
||||
|
||||
// Delete any existing sessions just to be sure
|
||||
$this->authServer->getStorage('session')->deleteSession($authParams['client_id'], 'client', $authParams['client_id']);
|
||||
|
||||
// Create a new session
|
||||
$sessionId = $this->authServer->getStorage('session')->createSession($authParams['client_id'], 'client', $authParams['client_id']);
|
||||
|
||||
// Add the access token
|
||||
$accessTokenId = $this->authServer->getStorage('session')->associateAccessToken($sessionId, $accessToken, $accessTokenExpires);
|
||||
|
||||
// Associate scopes with the new session
|
||||
foreach ($authParams['scopes'] as $scope)
|
||||
{
|
||||
$this->authServer->getStorage('session')->associateScope($accessTokenId, $scope['id']);
|
||||
}
|
||||
|
||||
$response = array(
|
||||
'access_token' => $accessToken,
|
||||
'token_type' => 'bearer',
|
||||
'expires' => $accessTokenExpires,
|
||||
'expires_in' => $accessTokenExpiresIn
|
||||
);
|
||||
|
||||
return $response;
|
||||
}
|
||||
|
||||
}
|
@@ -1,61 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* OAuth 2.0 Grant type interface
|
||||
*
|
||||
* @package php-loep/oauth2-server
|
||||
* @author Alex Bilbie <hello@alexbilbie.com>
|
||||
* @copyright Copyright (c) 2013 PHP League of Extraordinary Packages
|
||||
* @license http://mit-license.org/
|
||||
* @link http://github.com/php-loep/oauth2-server
|
||||
*/
|
||||
|
||||
namespace League\OAuth2\Server\Grant;
|
||||
|
||||
use League\OAuth2\Server\Request;
|
||||
use League\OAuth2\Server\Authorization;
|
||||
use League\OAuth2\Server\Exception;
|
||||
use League\OAuth2\Server\Util\SecureKey;
|
||||
use League\OAuth2\Server\Storage\SessionInterface;
|
||||
use League\OAuth2\Server\Storage\ClientInterface;
|
||||
use League\OAuth2\Server\Storage\ScopeInterface;
|
||||
|
||||
interface GrantTypeInterface
|
||||
{
|
||||
/**
|
||||
* Constructor
|
||||
* @param Authorization $authServer Authorization server instance
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(Authorization $authServer);
|
||||
|
||||
/**
|
||||
* Returns the grant identifier (used to validate grant_type in League\OAuth2\Server\Authorization::issueAccessToken())
|
||||
* @return string
|
||||
*/
|
||||
public function getIdentifier();
|
||||
|
||||
/**
|
||||
* Returns the response type (used to validate response_type in League\OAuth2\Server\Grant\AuthCode::checkAuthoriseParams())
|
||||
* @return null|string
|
||||
*/
|
||||
public function getResponseType();
|
||||
|
||||
/**
|
||||
* Complete the grant flow
|
||||
*
|
||||
* Example response:
|
||||
* <code>
|
||||
* array(
|
||||
* 'access_token' => (string), // The access token
|
||||
* 'refresh_token' => (string), // The refresh token (only set if the refresh token grant is enabled)
|
||||
* 'token_type' => 'bearer', // Almost always "bearer" (exceptions: JWT, SAML)
|
||||
* 'expires' => (int), // The timestamp of when the access token will expire
|
||||
* 'expires_in' => (int) // The number of seconds before the access token will expire
|
||||
* )
|
||||
* </code>
|
||||
*
|
||||
* @param null|array $inputParams Null unless the input parameters have been manually set
|
||||
* @return array An array of parameters to be passed back to the client
|
||||
*/
|
||||
public function completeFlow($inputParams = null);
|
||||
}
|
@@ -1,107 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* OAuth 2.0 implicit grant
|
||||
*
|
||||
* @package php-loep/oauth2-server
|
||||
* @author Alex Bilbie <hello@alexbilbie.com>
|
||||
* @copyright Copyright (c) 2013 PHP League of Extraordinary Packages
|
||||
* @license http://mit-license.org/
|
||||
* @link http://github.com/php-loep/oauth2-server
|
||||
*/
|
||||
|
||||
namespace League\OAuth2\Server\Grant;
|
||||
|
||||
use League\OAuth2\Server\Request;
|
||||
use League\OAuth2\Server\Authorization;
|
||||
use League\OAuth2\Server\Exception;
|
||||
use League\OAuth2\Server\Util\SecureKey;
|
||||
use League\OAuth2\Server\Storage\SessionInterface;
|
||||
use League\OAuth2\Server\Storage\ClientInterface;
|
||||
use League\OAuth2\Server\Storage\ScopeInterface;
|
||||
|
||||
/**
|
||||
* Client credentials grant class
|
||||
*/
|
||||
class Implict implements GrantTypeInterface {
|
||||
|
||||
/**
|
||||
* Grant identifier
|
||||
* @var string
|
||||
*/
|
||||
protected $identifier = 'implicit';
|
||||
|
||||
/**
|
||||
* Response type
|
||||
* @var string
|
||||
*/
|
||||
protected $responseType = 'token';
|
||||
|
||||
/**
|
||||
* AuthServer instance
|
||||
* @var AuthServer
|
||||
*/
|
||||
protected $authServer = null;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
* @param Authorization $authServer Authorization server instance
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(Authorization $authServer)
|
||||
{
|
||||
$this->authServer = $authServer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the identifier
|
||||
* @return string
|
||||
*/
|
||||
public function getIdentifier()
|
||||
{
|
||||
return $this->identifier;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the response type
|
||||
* @return string
|
||||
*/
|
||||
public function getResponseType()
|
||||
{
|
||||
return $this->responseType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Complete the client credentials grant
|
||||
* @param null|array $inputParams
|
||||
* @return array
|
||||
*/
|
||||
public function completeFlow($authParams = null)
|
||||
{
|
||||
// Remove any old sessions the user might have
|
||||
$this->authServer->getStorage('session')->deleteSession($authParams['client_id'], 'user', $authParams['user_id']);
|
||||
|
||||
// Generate a new access token
|
||||
$accessToken = SecureKey::make();
|
||||
|
||||
// Compute expiry time
|
||||
$accessTokenExpires = time() + $this->authServer->getAccessTokenTTL();
|
||||
|
||||
// Create a new session
|
||||
$sessionId = $this->authServer->getStorage('session')->createSession($authParams['client_id'], 'user', $authParams['user_id']);
|
||||
|
||||
// Create an access token
|
||||
$accessTokenId = $this->authServer->getStorage('session')->associateAccessToken($sessionId, $accessToken, $accessTokenExpires);
|
||||
|
||||
// Associate scopes with the access token
|
||||
foreach ($authParams['scopes'] as $scope) {
|
||||
$this->authServer->getStorage('session')->associateScope($accessTokenId, $scope['id']);
|
||||
}
|
||||
|
||||
$response = array(
|
||||
'access_token' => $accessToken
|
||||
);
|
||||
|
||||
return $response;
|
||||
}
|
||||
|
||||
}
|
@@ -1,224 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* OAuth 2.0 Password grant
|
||||
*
|
||||
* @package php-loep/oauth2-server
|
||||
* @author Alex Bilbie <hello@alexbilbie.com>
|
||||
* @copyright Copyright (c) 2013 PHP League of Extraordinary Packages
|
||||
* @license http://mit-license.org/
|
||||
* @link http://github.com/php-loep/oauth2-server
|
||||
*/
|
||||
|
||||
namespace League\OAuth2\Server\Grant;
|
||||
|
||||
use League\OAuth2\Server\Request;
|
||||
use League\OAuth2\Server\Authorization;
|
||||
use League\OAuth2\Server\Exception;
|
||||
use League\OAuth2\Server\Util\SecureKey;
|
||||
use League\OAuth2\Server\Storage\SessionInterface;
|
||||
use League\OAuth2\Server\Storage\ClientInterface;
|
||||
use League\OAuth2\Server\Storage\ScopeInterface;
|
||||
|
||||
/**
|
||||
* Password grant class
|
||||
*/
|
||||
class Password implements GrantTypeInterface {
|
||||
|
||||
/**
|
||||
* Grant identifier
|
||||
* @var string
|
||||
*/
|
||||
protected $identifier = 'password';
|
||||
|
||||
/**
|
||||
* Response type
|
||||
* @var string
|
||||
*/
|
||||
protected $responseType = null;
|
||||
|
||||
/**
|
||||
* Callback to authenticate a user's name and password
|
||||
* @var function
|
||||
*/
|
||||
protected $callback = null;
|
||||
|
||||
/**
|
||||
* AuthServer instance
|
||||
* @var AuthServer
|
||||
*/
|
||||
protected $authServer = null;
|
||||
|
||||
/**
|
||||
* Access token expires in override
|
||||
* @var int
|
||||
*/
|
||||
protected $accessTokenTTL = null;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
* @param Authorization $authServer Authorization server instance
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(Authorization $authServer)
|
||||
{
|
||||
$this->authServer = $authServer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the identifier
|
||||
* @return string
|
||||
*/
|
||||
public function getIdentifier()
|
||||
{
|
||||
return $this->identifier;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the response type
|
||||
* @return string
|
||||
*/
|
||||
public function getResponseType()
|
||||
{
|
||||
return $this->responseType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Override the default access token expire time
|
||||
* @param int $accessTokenTTL
|
||||
* @return void
|
||||
*/
|
||||
public function setAccessTokenTTL($accessTokenTTL)
|
||||
{
|
||||
$this->accessTokenTTL = $accessTokenTTL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the callback to verify a user's username and password
|
||||
* @param callable $callback The callback function
|
||||
* @return void
|
||||
*/
|
||||
public function setVerifyCredentialsCallback($callback)
|
||||
{
|
||||
$this->callback = $callback;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the callback function
|
||||
* @return callable
|
||||
*/
|
||||
protected function getVerifyCredentialsCallback()
|
||||
{
|
||||
if (is_null($this->callback) || ! is_callable($this->callback)) {
|
||||
throw new Exception\InvalidGrantTypeException('Null or non-callable callback set');
|
||||
}
|
||||
|
||||
return $this->callback;
|
||||
}
|
||||
|
||||
/**
|
||||
* Complete the password grant
|
||||
* @param null|array $inputParams
|
||||
* @return array
|
||||
*/
|
||||
public function completeFlow($inputParams = null)
|
||||
{
|
||||
// Get the required params
|
||||
$authParams = $this->authServer->getParam(array('client_id', 'client_secret', 'username', 'password'), 'post', $inputParams);
|
||||
|
||||
if (is_null($authParams['client_id'])) {
|
||||
throw new Exception\ClientException(sprintf($this->authServer->getExceptionMessage('invalid_request'), 'client_id'), 0);
|
||||
}
|
||||
|
||||
if (is_null($authParams['client_secret'])) {
|
||||
throw new Exception\ClientException(sprintf($this->authServer->getExceptionMessage('invalid_request'), 'client_secret'), 0);
|
||||
}
|
||||
|
||||
// Validate client credentials
|
||||
$clientDetails = $this->authServer->getStorage('client')->getClient($authParams['client_id'], $authParams['client_secret'], null, $this->identifier);
|
||||
|
||||
if ($clientDetails === false) {
|
||||
throw new Exception\ClientException($this->authServer->getExceptionMessage('invalid_client'), 8);
|
||||
}
|
||||
|
||||
$authParams['client_details'] = $clientDetails;
|
||||
|
||||
if (is_null($authParams['username'])) {
|
||||
throw new Exception\ClientException(sprintf($this->authServer->getExceptionMessage('invalid_request'), 'username'), 0);
|
||||
}
|
||||
|
||||
if (is_null($authParams['password'])) {
|
||||
throw new Exception\ClientException(sprintf($this->authServer->getExceptionMessage('invalid_request'), 'password'), 0);
|
||||
}
|
||||
|
||||
// Check if user's username and password are correct
|
||||
$userId = call_user_func($this->getVerifyCredentialsCallback(), $authParams['username'], $authParams['password']);
|
||||
|
||||
if ($userId === false) {
|
||||
throw new Exception\ClientException($this->authServer->getExceptionMessage('invalid_credentials'), 0);
|
||||
}
|
||||
|
||||
// Validate any scopes that are in the request
|
||||
$scope = $this->authServer->getParam('scope', 'post', $inputParams, '');
|
||||
$scopes = explode($this->authServer->getScopeDelimeter(), $scope);
|
||||
|
||||
for ($i = 0; $i < count($scopes); $i++) {
|
||||
$scopes[$i] = trim($scopes[$i]);
|
||||
if ($scopes[$i] === '') unset($scopes[$i]); // Remove any junk scopes
|
||||
}
|
||||
|
||||
if ($this->authServer->scopeParamRequired() === true && count($scopes) === 0) {
|
||||
throw new Exception\ClientException(sprintf($this->authServer->getExceptionMessage('invalid_request'), 'scope'), 0);
|
||||
} elseif (count($scopes) === 0 && $this->authServer->getDefaultScope()) {
|
||||
$scopes = array($this->authServer->getDefaultScope());
|
||||
}
|
||||
|
||||
$authParams['scopes'] = array();
|
||||
|
||||
foreach ($scopes as $scope) {
|
||||
$scopeDetails = $this->authServer->getStorage('scope')->getScope($scope, $authParams['client_id'], $this->identifier);
|
||||
|
||||
if ($scopeDetails === false) {
|
||||
throw new Exception\ClientException(sprintf($this->authServer->getExceptionMessage('invalid_scope'), $scope), 4);
|
||||
}
|
||||
|
||||
$authParams['scopes'][] = $scopeDetails;
|
||||
}
|
||||
|
||||
// Generate an access token
|
||||
$accessToken = SecureKey::make();
|
||||
$accessTokenExpiresIn = ($this->accessTokenTTL !== null) ? $this->accessTokenTTL : $this->authServer->getAccessTokenTTL();
|
||||
$accessTokenExpires = time() + $accessTokenExpiresIn;
|
||||
|
||||
// Delete any existing sessions just to be sure
|
||||
$this->authServer->getStorage('session')->deleteSession($authParams['client_id'], 'user', $userId);
|
||||
|
||||
// Create a new session
|
||||
$sessionId = $this->authServer->getStorage('session')->createSession($authParams['client_id'], 'user', $userId);
|
||||
|
||||
// Associate an access token with the session
|
||||
$accessTokenId = $this->authServer->getStorage('session')->associateAccessToken($sessionId, $accessToken, $accessTokenExpires);
|
||||
|
||||
// Associate scopes with the access token
|
||||
foreach ($authParams['scopes'] as $scope) {
|
||||
$this->authServer->getStorage('session')->associateScope($accessTokenId, $scope['id']);
|
||||
}
|
||||
|
||||
$response = array(
|
||||
'access_token' => $accessToken,
|
||||
'token_type' => 'bearer',
|
||||
'expires' => $accessTokenExpires,
|
||||
'expires_in' => $accessTokenExpiresIn
|
||||
);
|
||||
|
||||
// Associate a refresh token if set
|
||||
if ($this->authServer->hasGrantType('refresh_token')) {
|
||||
$refreshToken = SecureKey::make();
|
||||
$refreshTokenTTL = time() + $this->authServer->getGrantType('refresh_token')->getRefreshTokenTTL();
|
||||
$this->authServer->getStorage('session')->associateRefreshToken($accessTokenId, $refreshToken, $refreshTokenTTL);
|
||||
$response['refresh_token'] = $refreshToken;
|
||||
}
|
||||
|
||||
return $response;
|
||||
}
|
||||
|
||||
}
|
@@ -1,182 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* OAuth 2.0 Refresh token grant
|
||||
*
|
||||
* @package php-loep/oauth2-server
|
||||
* @author Alex Bilbie <hello@alexbilbie.com>
|
||||
* @copyright Copyright (c) 2013 PHP League of Extraordinary Packages
|
||||
* @license http://mit-license.org/
|
||||
* @link http://github.com/php-loep/oauth2-server
|
||||
*/
|
||||
|
||||
namespace League\OAuth2\Server\Grant;
|
||||
|
||||
use League\OAuth2\Server\Request;
|
||||
use League\OAuth2\Server\Authorization;
|
||||
use League\OAuth2\Server\Exception;
|
||||
use League\OAuth2\Server\Util\SecureKey;
|
||||
use League\OAuth2\Server\Storage\SessionInterface;
|
||||
use League\OAuth2\Server\Storage\ClientInterface;
|
||||
use League\OAuth2\Server\Storage\ScopeInterface;
|
||||
|
||||
/**
|
||||
* Referesh token grant
|
||||
*/
|
||||
class RefreshToken implements GrantTypeInterface {
|
||||
|
||||
/**
|
||||
* Grant identifier
|
||||
* @var string
|
||||
*/
|
||||
protected $identifier = 'refresh_token';
|
||||
|
||||
/**
|
||||
* Response type
|
||||
* @var string
|
||||
*/
|
||||
protected $responseType = null;
|
||||
|
||||
/**
|
||||
* AuthServer instance
|
||||
* @var AuthServer
|
||||
*/
|
||||
protected $authServer = null;
|
||||
|
||||
/**
|
||||
* Access token expires in override
|
||||
* @var int
|
||||
*/
|
||||
protected $accessTokenTTL = null;
|
||||
|
||||
/**
|
||||
* Refresh token TTL
|
||||
* @var integer
|
||||
*/
|
||||
protected $refreshTokenTTL = 604800;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
* @param Authorization $authServer Authorization server instance
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(Authorization $authServer)
|
||||
{
|
||||
$this->authServer = $authServer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the identifier
|
||||
* @return string
|
||||
*/
|
||||
public function getIdentifier()
|
||||
{
|
||||
return $this->identifier;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the response type
|
||||
* @return string
|
||||
*/
|
||||
public function getResponseType()
|
||||
{
|
||||
return $this->responseType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Override the default access token expire time
|
||||
* @param int $accessTokenTTL
|
||||
* @return void
|
||||
*/
|
||||
public function setAccessTokenTTL($accessTokenTTL)
|
||||
{
|
||||
$this->accessTokenTTL = $accessTokenTTL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the TTL of the refresh token
|
||||
* @param int $refreshTokenTTL
|
||||
* @return void
|
||||
*/
|
||||
public function setRefreshTokenTTL($refreshTokenTTL)
|
||||
{
|
||||
$this->refreshTokenTTL = $refreshTokenTTL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the TTL of the refresh token
|
||||
* @return int
|
||||
*/
|
||||
public function getRefreshTokenTTL()
|
||||
{
|
||||
return $this->refreshTokenTTL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Complete the refresh token grant
|
||||
* @param null|array $inputParams
|
||||
* @return array
|
||||
*/
|
||||
public function completeFlow($inputParams = null)
|
||||
{
|
||||
// Get the required params
|
||||
$authParams = $this->authServer->getParam(array('client_id', 'client_secret', 'refresh_token'), 'post', $inputParams);
|
||||
|
||||
if (is_null($authParams['client_id'])) {
|
||||
throw new Exception\ClientException(sprintf($this->authServer->getExceptionMessage('invalid_request'), 'client_id'), 0);
|
||||
}
|
||||
|
||||
if (is_null($authParams['client_secret'])) {
|
||||
throw new Exception\ClientException(sprintf($this->authServer->getExceptionMessage('invalid_request'), 'client_secret'), 0);
|
||||
}
|
||||
|
||||
// Validate client ID and client secret
|
||||
$clientDetails = $this->authServer->getStorage('client')->getClient($authParams['client_id'], $authParams['client_secret'], null, $this->identifier);
|
||||
|
||||
if ($clientDetails === false) {
|
||||
throw new Exception\ClientException($this->authServer->getExceptionMessage('invalid_client'), 8);
|
||||
}
|
||||
|
||||
$authParams['client_details'] = $clientDetails;
|
||||
|
||||
if (is_null($authParams['refresh_token'])) {
|
||||
throw new Exception\ClientException(sprintf($this->authServer->getExceptionMessage('invalid_request'), 'refresh_token'), 0);
|
||||
}
|
||||
|
||||
// Validate refresh token
|
||||
$accessTokenId = $this->authServer->getStorage('session')->validateRefreshToken($authParams['refresh_token']);
|
||||
|
||||
if ($accessTokenId === false) {
|
||||
throw new Exception\ClientException($this->authServer->getExceptionMessage('invalid_refresh'), 0);
|
||||
}
|
||||
|
||||
// Get the existing access token
|
||||
$accessTokenDetails = $this->authServer->getStorage('session')->getAccessToken($accessTokenId);
|
||||
|
||||
// Get the scopes for the existing access token
|
||||
$scopes = $this->authServer->getStorage('session')->getScopes($accessTokenDetails['access_token']);
|
||||
|
||||
// Generate new tokens and associate them to the session
|
||||
$accessToken = SecureKey::make();
|
||||
$accessTokenExpiresIn = ($this->accessTokenTTL !== null) ? $this->accessTokenTTL : $this->authServer->getAccessTokenTTL();
|
||||
$accessTokenExpires = time() + $accessTokenExpiresIn;
|
||||
$refreshToken = SecureKey::make();
|
||||
$refreshTokenExpires = time() + $this->getRefreshTokenTTL();
|
||||
|
||||
$newAccessTokenId = $this->authServer->getStorage('session')->associateAccessToken($accessTokenDetails['session_id'], $accessToken, $accessTokenExpires);
|
||||
|
||||
foreach ($scopes as $scope) {
|
||||
$this->authServer->getStorage('session')->associateScope($newAccessTokenId, $scope['id']);
|
||||
}
|
||||
|
||||
$this->authServer->getStorage('session')->associateRefreshToken($newAccessTokenId, $refreshToken, $refreshTokenExpires);
|
||||
|
||||
return array(
|
||||
'access_token' => $accessToken,
|
||||
'refresh_token' => $refreshToken,
|
||||
'token_type' => 'bearer',
|
||||
'expires' => $accessTokenExpires,
|
||||
'expires_in' => $accessTokenExpiresIn
|
||||
);
|
||||
}
|
||||
|
||||
}
|
@@ -1,259 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* OAuth 2.0 Resource Server
|
||||
*
|
||||
* @package php-loep/oauth2-server
|
||||
* @author Alex Bilbie <hello@alexbilbie.com>
|
||||
* @copyright Copyright (c) 2013 PHP League of Extraordinary Packages
|
||||
* @license http://mit-license.org/
|
||||
* @link http://github.com/php-loep/oauth2-server
|
||||
*/
|
||||
|
||||
namespace League\OAuth2\Server;
|
||||
|
||||
use OutOfBoundsException;
|
||||
use League\OAuth2\Server\Storage\SessionInterface;
|
||||
use League\OAuth2\Server\Util\RequestInterface;
|
||||
use League\OAuth2\Server\Util\Request;
|
||||
|
||||
/**
|
||||
* OAuth 2.0 Resource Server
|
||||
*/
|
||||
class Resource
|
||||
{
|
||||
/**
|
||||
* The access token
|
||||
* @var string
|
||||
*/
|
||||
protected $accessToken = null;
|
||||
|
||||
/**
|
||||
* The session ID
|
||||
* @var string
|
||||
*/
|
||||
protected $sessionId = null;
|
||||
|
||||
/**
|
||||
* The type of the owner of the access token
|
||||
* @var string
|
||||
*/
|
||||
protected $ownerType = null;
|
||||
|
||||
/**
|
||||
* The ID of the owner of the access token
|
||||
* @var string
|
||||
*/
|
||||
protected $ownerId = null;
|
||||
|
||||
/**
|
||||
* The scopes associated with the access token
|
||||
* @var array
|
||||
*/
|
||||
protected $sessionScopes = array();
|
||||
|
||||
/**
|
||||
* The client, scope and session storage classes
|
||||
* @var array
|
||||
*/
|
||||
protected $storages = array();
|
||||
|
||||
/**
|
||||
* The request object
|
||||
* @var Util\RequestInterface
|
||||
*/
|
||||
protected $request = null;
|
||||
|
||||
/**
|
||||
* The query string key which is used by clients to present the access token (default: access_token)
|
||||
* @var string
|
||||
*/
|
||||
protected $tokenKey = 'access_token';
|
||||
|
||||
/**
|
||||
* The client ID
|
||||
* @var string
|
||||
*/
|
||||
protected $clientId = null;
|
||||
|
||||
/**
|
||||
* Sets up the Resource
|
||||
*
|
||||
* @param SessionInterface The Session Storage Object
|
||||
*/
|
||||
public function __construct(SessionInterface $session)
|
||||
{
|
||||
$this->storages['session'] = $session;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the Request Object
|
||||
*
|
||||
* @param RequestInterface The Request Object
|
||||
*/
|
||||
public function setRequest(RequestInterface $request)
|
||||
{
|
||||
$this->request = $request;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the Request object. It will create one from the globals if one is not set.
|
||||
*
|
||||
* @return Util\RequestInterface
|
||||
*/
|
||||
public function getRequest()
|
||||
{
|
||||
if ($this->request === null) {
|
||||
// @codeCoverageIgnoreStart
|
||||
$this->request = Request::buildFromGlobals();
|
||||
}
|
||||
// @codeCoverageIgnoreEnd
|
||||
|
||||
return $this->request;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the query string key for the access token.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getTokenKey()
|
||||
{
|
||||
return $this->tokenKey;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the query string key for the access token.
|
||||
*
|
||||
* @param $key The new query string key
|
||||
*/
|
||||
public function setTokenKey($key)
|
||||
{
|
||||
$this->tokenKey = $key;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the access token owner ID.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getOwnerId()
|
||||
{
|
||||
return $this->ownerId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the owner type.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getOwnerType()
|
||||
{
|
||||
return $this->ownerType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the access token.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getAccessToken()
|
||||
{
|
||||
return $this->accessToken;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the client ID that created the session
|
||||
* @return string
|
||||
*/
|
||||
public function getClientId()
|
||||
{
|
||||
return $this->clientId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the access token is valid or not.
|
||||
*
|
||||
* @throws Exception\InvalidAccessTokenException Thrown if the presented access token is not valid
|
||||
* @return bool
|
||||
*/
|
||||
public function isValid()
|
||||
{
|
||||
$accessToken = $this->determineAccessToken();
|
||||
|
||||
$result = $this->storages['session']->validateAccessToken($accessToken);
|
||||
|
||||
if ( ! $result) {
|
||||
throw new Exception\InvalidAccessTokenException('Access token is not valid');
|
||||
}
|
||||
|
||||
$this->accessToken = $accessToken;
|
||||
$this->sessionId = $result['session_id'];
|
||||
$this->clientId = $result['client_id'];
|
||||
$this->ownerType = $result['owner_type'];
|
||||
$this->ownerId = $result['owner_id'];
|
||||
|
||||
$sessionScopes = $this->storages['session']->getScopes($this->accessToken);
|
||||
foreach ($sessionScopes as $scope) {
|
||||
$this->sessionScopes[] = $scope['key'];
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the session scopes
|
||||
* @return array
|
||||
*/
|
||||
public function getScopes()
|
||||
{
|
||||
return $this->sessionScopes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the presented access token has the given scope(s).
|
||||
*
|
||||
* @param array|string An array of scopes or a single scope as a string
|
||||
* @return bool Returns bool if all scopes are found, false if any fail
|
||||
*/
|
||||
public function hasScope($scopes)
|
||||
{
|
||||
if (is_string($scopes)) {
|
||||
if (in_array($scopes, $this->sessionScopes)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
} elseif (is_array($scopes)) {
|
||||
foreach ($scopes as $scope) {
|
||||
if ( ! in_array($scope, $this->sessionScopes)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads in the access token from the headers.
|
||||
*
|
||||
* @throws Exception\MissingAccessTokenException Thrown if there is no access token presented
|
||||
* @return string
|
||||
*/
|
||||
protected function determineAccessToken()
|
||||
{
|
||||
if ($header = $this->getRequest()->header('Authorization')) {
|
||||
$accessToken = trim(str_replace('Bearer', '', $header));
|
||||
} else {
|
||||
$method = $this->getRequest()->server('REQUEST_METHOD');
|
||||
$accessToken = $this->getRequest()->{$method}($this->tokenKey);
|
||||
}
|
||||
|
||||
if (empty($accessToken)) {
|
||||
throw new Exception\InvalidAccessTokenException('Access token is missing');
|
||||
}
|
||||
|
||||
return $accessToken;
|
||||
}
|
||||
|
||||
}
|
@@ -1,57 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* OAuth 2.0 Client storage interface
|
||||
*
|
||||
* @package php-loep/oauth2-server
|
||||
* @author Alex Bilbie <hello@alexbilbie.com>
|
||||
* @copyright Copyright (c) 2013 PHP League of Extraordinary Packages
|
||||
* @license http://mit-license.org/
|
||||
* @link http://github.com/php-loep/oauth2-server
|
||||
*/
|
||||
|
||||
namespace League\OAuth2\Server\Storage;
|
||||
|
||||
interface ClientInterface
|
||||
{
|
||||
/**
|
||||
* Validate a client
|
||||
*
|
||||
* Example SQL query:
|
||||
*
|
||||
* <code>
|
||||
* # Client ID + redirect URI
|
||||
* SELECT oauth_clients.id, oauth_clients.secret, oauth_client_endpoints.redirect_uri, oauth_clients.name
|
||||
* FROM oauth_clients LEFT JOIN oauth_client_endpoints ON oauth_client_endpoints.client_id = oauth_clients.id
|
||||
* WHERE oauth_clients.id = :clientId AND oauth_client_endpoints.redirect_uri = :redirectUri
|
||||
*
|
||||
* # Client ID + client secret
|
||||
* SELECT oauth_clients.id, oauth_clients.secret, oauth_clients.name FROM oauth_clients WHERE
|
||||
* oauth_clients.id = :clientId AND oauth_clients.secret = :clientSecret
|
||||
*
|
||||
* # Client ID + client secret + redirect URI
|
||||
* SELECT oauth_clients.id, oauth_clients.secret, oauth_client_endpoints.redirect_uri, oauth_clients.name FROM
|
||||
* oauth_clients LEFT JOIN oauth_client_endpoints ON oauth_client_endpoints.client_id = oauth_clients.id
|
||||
* WHERE oauth_clients.id = :clientId AND oauth_clients.secret = :clientSecret AND
|
||||
* oauth_client_endpoints.redirect_uri = :redirectUri
|
||||
* </code>
|
||||
*
|
||||
* Response:
|
||||
*
|
||||
* <code>
|
||||
* Array
|
||||
* (
|
||||
* [client_id] => (string) The client ID
|
||||
* [client secret] => (string) The client secret
|
||||
* [redirect_uri] => (string) The redirect URI used in this request
|
||||
* [name] => (string) The name of the client
|
||||
* )
|
||||
* </code>
|
||||
*
|
||||
* @param string $clientId The client's ID
|
||||
* @param string $clientSecret The client's secret (default = "null")
|
||||
* @param string $redirectUri The client's redirect URI (default = "null")
|
||||
* @param string $grantType The grant type used in the request
|
||||
* @return bool|array Returns false if the validation fails, array on success
|
||||
*/
|
||||
public function getClient($clientId, $clientSecret = null, $redirectUri = null, $grantType);
|
||||
}
|
@@ -1,45 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace League\OAuth2\Server\Storage\PDO;
|
||||
|
||||
use League\OAuth2\Server\Storage\ClientInterface;
|
||||
|
||||
class Client implements ClientInterface
|
||||
{
|
||||
public function getClient($clientId, $clientSecret = null, $redirectUri = null, $grantType)
|
||||
{
|
||||
$db = \ezcDbInstance::get();
|
||||
|
||||
if ( ! is_null($redirectUri) && is_null($clientSecret)) {
|
||||
$stmt = $db->prepare('SELECT oauth_clients.id, oauth_clients.secret, oauth_client_endpoints.redirect_uri, oauth_clients.name FROM oauth_clients LEFT JOIN oauth_client_endpoints ON oauth_client_endpoints.client_id = oauth_clients.id WHERE oauth_clients.id = :clientId AND oauth_client_endpoints.redirect_uri = :redirectUri');
|
||||
$stmt->bindValue(':redirectUri', $redirectUri);
|
||||
}
|
||||
|
||||
elseif ( ! is_null($clientSecret) && is_null($redirectUri)) {
|
||||
$stmt = $db->prepare('SELECT oauth_clients.id, oauth_clients.secret, oauth_clients.name FROM oauth_clients WHERE oauth_clients.id = :clientId AND oauth_clients.secret = :clientSecret');
|
||||
$stmt->bindValue(':clientSecret', $clientSecret);
|
||||
}
|
||||
|
||||
elseif ( ! is_null($clientSecret) && ! is_null($redirectUri)) {
|
||||
$stmt = $db->prepare('SELECT oauth_clients.id, oauth_clients.secret, oauth_client_endpoints.redirect_uri, oauth_clients.name FROM oauth_clients LEFT JOIN oauth_client_endpoints ON oauth_client_endpoints.client_id = oauth_clients.id WHERE oauth_clients.id = :clientId AND oauth_clients.secret = :clientSecret AND oauth_client_endpoints.redirect_uri = :redirectUri');
|
||||
$stmt->bindValue(':redirectUri', $redirectUri);
|
||||
$stmt->bindValue(':clientSecret', $clientSecret);
|
||||
}
|
||||
|
||||
$stmt->bindValue(':clientId', $clientId);
|
||||
$stmt->execute();
|
||||
|
||||
$row = $stmt->fetchObject();
|
||||
|
||||
if ($row === false) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return array(
|
||||
'client_id' => $row->id,
|
||||
'client_secret' => $row->secret,
|
||||
'redirect_uri' => (isset($row->redirect_uri)) ? $row->redirect_uri : null,
|
||||
'name' => $row->name
|
||||
);
|
||||
}
|
||||
}
|
@@ -1,17 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace League\OAuth2\Server\Storage\PDO;
|
||||
|
||||
class Db
|
||||
{
|
||||
/**
|
||||
* Db constructor
|
||||
* @param array|string $dsn Connection DSN string or array of parameters
|
||||
* @return void
|
||||
*/
|
||||
public function __construct($dsn = '')
|
||||
{
|
||||
$db = \ezcDbFactory::create($dsn);
|
||||
\ezcDbInstance::set($db);
|
||||
}
|
||||
}
|
@@ -1,31 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace League\OAuth2\Server\Storage\PDO;
|
||||
|
||||
use League\OAuth2\Server\Storage\ScopeInterface;
|
||||
|
||||
class Scope implements ScopeInterface
|
||||
{
|
||||
public function getScope($scope, $clientId = null, $grantType = null)
|
||||
{
|
||||
$db = \ezcDbInstance::get();
|
||||
|
||||
$stmt = $db->prepare('SELECT * FROM oauth_scopes WHERE oauth_scopes.key = :scope');
|
||||
$stmt->bindValue(':scope', $scope);
|
||||
$stmt->execute();
|
||||
|
||||
$row = $stmt->fetchObject();
|
||||
|
||||
if ($row === false) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return array(
|
||||
'id' => $row->id,
|
||||
'scope' => $row->key,
|
||||
'name' => $row->name,
|
||||
'description' => $row->description
|
||||
);
|
||||
|
||||
}
|
||||
}
|
@@ -1,253 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace League\OAuth2\Server\Storage\PDO;
|
||||
|
||||
use League\OAuth2\Server\Storage\SessionInterface;
|
||||
|
||||
class Session implements SessionInterface
|
||||
{
|
||||
/**
|
||||
* Create a new session
|
||||
* @param string $clientId The client ID
|
||||
* @param string $ownerType The type of the session owner (e.g. "user")
|
||||
* @param string $ownerId The ID of the session owner (e.g. "123")
|
||||
* @return int The session ID
|
||||
*/
|
||||
public function createSession($clientId, $ownerType, $ownerId)
|
||||
{
|
||||
$db = \ezcDbInstance::get();
|
||||
|
||||
$stmt = $db->prepare('INSERT INTO oauth_sessions (client_id, owner_type, owner_id) VALUE
|
||||
(:clientId, :ownerType, :ownerId)');
|
||||
$stmt->bindValue(':clientId', $clientId);
|
||||
$stmt->bindValue(':ownerType', $ownerType);
|
||||
$stmt->bindValue(':ownerId', $ownerId);
|
||||
$stmt->execute();
|
||||
|
||||
return $db->lastInsertId();
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete a session
|
||||
* @param string $clientId The client ID
|
||||
* @param string $ownerType The type of the session owner (e.g. "user")
|
||||
* @param string $ownerId The ID of the session owner (e.g. "123")
|
||||
* @return void
|
||||
*/
|
||||
public function deleteSession($clientId, $ownerType, $ownerId)
|
||||
{
|
||||
$db = \ezcDbInstance::get();
|
||||
|
||||
$stmt = $db->prepare('DELETE FROM oauth_sessions WHERE client_id = :clientId AND
|
||||
owner_type = :type AND owner_id = :typeId');
|
||||
$stmt->bindValue(':clientId', $clientId);
|
||||
$stmt->bindValue(':type', $ownerType);
|
||||
$stmt->bindValue(':typeId', $ownerId);
|
||||
$stmt->execute();
|
||||
}
|
||||
|
||||
/**
|
||||
* Associate a redirect URI with a session
|
||||
* @param int $sessionId The session ID
|
||||
* @param string $redirectUri The redirect URI
|
||||
* @return void
|
||||
*/
|
||||
public function associateRedirectUri($sessionId, $redirectUri)
|
||||
{
|
||||
$db = \ezcDbInstance::get();
|
||||
|
||||
$stmt = $db->prepare('INSERT INTO oauth_session_redirects (session_id, redirect_uri)
|
||||
VALUE (:sessionId, :redirectUri)');
|
||||
$stmt->bindValue(':sessionId', $sessionId);
|
||||
$stmt->bindValue(':redirectUri', $redirectUri);
|
||||
$stmt->execute();
|
||||
}
|
||||
|
||||
/**
|
||||
* Associate an access token with a session
|
||||
* @param int $sessionId The session ID
|
||||
* @param string $accessToken The access token
|
||||
* @param int $expireTime Unix timestamp of the access token expiry time
|
||||
* @return void
|
||||
*/
|
||||
public function associateAccessToken($sessionId, $accessToken, $expireTime)
|
||||
{
|
||||
$db = \ezcDbInstance::get();
|
||||
|
||||
$stmt = $db->prepare('INSERT INTO oauth_session_access_tokens (session_id, access_token, access_token_expires)
|
||||
VALUE (:sessionId, :accessToken, :accessTokenExpire)');
|
||||
$stmt->bindValue(':sessionId', $sessionId);
|
||||
$stmt->bindValue(':accessToken', $accessToken);
|
||||
$stmt->bindValue(':accessTokenExpire', $expireTime);
|
||||
$stmt->execute();
|
||||
|
||||
return $db->lastInsertId();
|
||||
}
|
||||
|
||||
/**
|
||||
* Associate a refresh token with a session
|
||||
* @param int $accessTokenId The access token ID
|
||||
* @param string $refreshToken The refresh token
|
||||
* @param int $expireTime Unix timestamp of the refresh token expiry time
|
||||
* @return void
|
||||
*/
|
||||
public function associateRefreshToken($accessTokenId, $refreshToken, $expireTime)
|
||||
{
|
||||
$db = \ezcDbInstance::get();
|
||||
|
||||
$stmt = $db->prepare('INSERT INTO oauth_session_refresh_tokens (session_access_token_id, refresh_token, refresh_token_expires) VALUE
|
||||
(:accessTokenId, :refreshToken, :expireTime)');
|
||||
$stmt->bindValue(':accessTokenId', $accessTokenId);
|
||||
$stmt->bindValue(':refreshToken', $refreshToken);
|
||||
$stmt->bindValue(':expireTime', $expireTime);
|
||||
$stmt->execute();
|
||||
}
|
||||
|
||||
/**
|
||||
* Assocate an authorization code with a session
|
||||
* @param int $sessionId The session ID
|
||||
* @param string $authCode The authorization code
|
||||
* @param int $expireTime Unix timestamp of the access token expiry time
|
||||
* @param string $scopeIds Comma seperated list of scope IDs to be later associated (default = null)
|
||||
* @return void
|
||||
*/
|
||||
public function associateAuthCode($sessionId, $authCode, $expireTime, $scopeIds = null)
|
||||
{
|
||||
$db = \ezcDbInstance::get();
|
||||
|
||||
$stmt = $db->prepare('INSERT INTO oauth_session_authcodes (session_id, auth_code, auth_code_expires, scope_ids)
|
||||
VALUE (:sessionId, :authCode, :authCodeExpires, :scopeIds)');
|
||||
$stmt->bindValue(':sessionId', $sessionId);
|
||||
$stmt->bindValue(':authCode', $authCode);
|
||||
$stmt->bindValue(':authCodeExpires', $expireTime);
|
||||
$stmt->bindValue(':scopeIds', $scopeIds);
|
||||
$stmt->execute();
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove an associated authorization token from a session
|
||||
* @param int $sessionId The session ID
|
||||
* @return void
|
||||
*/
|
||||
public function removeAuthCode($sessionId)
|
||||
{
|
||||
$db = \ezcDbInstance::get();
|
||||
|
||||
$stmt = $db->prepare('DELETE FROM oauth_session_authcodes WHERE session_id = :sessionId');
|
||||
$stmt->bindValue(':sessionId', $sessionId);
|
||||
$stmt->execute();
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate an authorization code
|
||||
* @param string $clientId The client ID
|
||||
* @param string $redirectUri The redirect URI
|
||||
* @param string $authCode The authorization code
|
||||
* @return void
|
||||
*/
|
||||
public function validateAuthCode($clientId, $redirectUri, $authCode)
|
||||
{
|
||||
$db = \ezcDbInstance::get();
|
||||
|
||||
$stmt = $db->prepare('SELECT oauth_sessions.id, oauth_session_authcodes.scope_ids FROM oauth_sessions JOIN
|
||||
oauth_session_authcodes ON oauth_session_authcodes.`session_id` = oauth_sessions.id JOIN
|
||||
oauth_session_redirects ON oauth_session_redirects.`session_id` = oauth_sessions.id WHERE
|
||||
oauth_sessions.client_id = :clientId AND oauth_session_authcodes.`auth_code` = :authCode AND
|
||||
`oauth_session_authcodes`.`auth_code_expires` >= :time AND `oauth_session_redirects`.`redirect_uri`
|
||||
= :redirectUri');
|
||||
$stmt->bindValue(':clientId', $clientId);
|
||||
$stmt->bindValue(':redirectUri', $redirectUri);
|
||||
$stmt->bindValue(':authCode', $authCode);
|
||||
$stmt->bindValue(':time', time());
|
||||
$stmt->execute();
|
||||
|
||||
$result = $stmt->fetchObject();
|
||||
|
||||
return ($result === false) ? false : (array) $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate an access token
|
||||
* @param string $accessToken The access token to be validated
|
||||
* @return void
|
||||
*/
|
||||
public function validateAccessToken($accessToken)
|
||||
{
|
||||
$db = \ezcDbInstance::get();
|
||||
|
||||
$stmt = $db->prepare('SELECT session_id, oauth_sessions.`client_id`, oauth_sessions.`owner_id`, oauth_sessions.`owner_type` FROM `oauth_session_access_tokens` JOIN oauth_sessions ON oauth_sessions.`id` = session_id WHERE access_token = :accessToken AND access_token_expires >= ' . time());
|
||||
$stmt->bindValue(':accessToken', $accessToken);
|
||||
$stmt->execute();
|
||||
|
||||
$result = $stmt->fetchObject();
|
||||
return ($result === false) ? false : (array) $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate a refresh token
|
||||
* @param string $refreshToken The access token
|
||||
* @return void
|
||||
*/
|
||||
public function validateRefreshToken($refreshToken)
|
||||
{
|
||||
$db = \ezcDbInstance::get();
|
||||
|
||||
$stmt = $db->prepare('SELECT session_access_token_id FROM `oauth_session_refresh_tokens` WHERE
|
||||
refresh_token = :refreshToken AND refresh_token_expires >= ' . time());
|
||||
$stmt->bindValue(':refreshToken', $refreshToken);
|
||||
$stmt->execute();
|
||||
|
||||
$result = $stmt->fetchObject();
|
||||
return ($result === false) ? false : $result->session_access_token_id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an access token by ID
|
||||
* @param int $accessTokenId The access token ID
|
||||
* @return array
|
||||
*/
|
||||
public function getAccessToken($accessTokenId)
|
||||
{
|
||||
$db = \ezcDbInstance::get();
|
||||
|
||||
$stmt = $db->prepare('SELECT * FROM `oauth_session_access_tokens` WHERE `id` = :accessTokenId');
|
||||
$stmt->bindValue(':accessTokenId', $accessTokenId);
|
||||
$stmt->execute();
|
||||
|
||||
$result = $stmt->fetchObject();
|
||||
return ($result === false) ? false : (array) $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Associate a scope with an access token
|
||||
* @param int $accessTokenId The ID of the access token
|
||||
* @param int $scopeId The ID of the scope
|
||||
* @return void
|
||||
*/
|
||||
public function associateScope($accessTokenId, $scopeId)
|
||||
{
|
||||
$db = \ezcDbInstance::get();
|
||||
|
||||
$stmt = $db->prepare('INSERT INTO `oauth_session_token_scopes` (`session_access_token_id`, `scope_id`)
|
||||
VALUE (:accessTokenId, :scopeId)');
|
||||
$stmt->bindValue(':accessTokenId', $accessTokenId);
|
||||
$stmt->bindValue(':scopeId', $scopeId);
|
||||
$stmt->execute();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all associated access tokens for an access token
|
||||
* @param string $accessToken The access token
|
||||
* @return array
|
||||
*/
|
||||
public function getScopes($accessToken)
|
||||
{
|
||||
$db = \ezcDbInstance::get();
|
||||
|
||||
$stmt = $db->prepare('SELECT oauth_scopes.* FROM oauth_session_token_scopes JOIN oauth_session_access_tokens ON oauth_session_access_tokens.`id` = `oauth_session_token_scopes`.`session_access_token_id` JOIN oauth_scopes ON oauth_scopes.id = `oauth_session_token_scopes`.`scope_id` WHERE access_token = :accessToken');
|
||||
$stmt->bindValue(':accessToken', $accessToken);
|
||||
$stmt->execute();
|
||||
|
||||
return $stmt->fetchAll();
|
||||
}
|
||||
}
|
@@ -1,43 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* OAuth 2.0 Scope storage interface
|
||||
*
|
||||
* @package php-loep/oauth2-server
|
||||
* @author Alex Bilbie <hello@alexbilbie.com>
|
||||
* @copyright Copyright (c) 2013 PHP League of Extraordinary Packages
|
||||
* @license http://mit-license.org/
|
||||
* @link http://github.com/php-loep/oauth2-server
|
||||
*/
|
||||
|
||||
namespace League\OAuth2\Server\Storage;
|
||||
|
||||
interface ScopeInterface
|
||||
{
|
||||
/**
|
||||
* Return information about a scope
|
||||
*
|
||||
* Example SQL query:
|
||||
*
|
||||
* <code>
|
||||
* SELECT * FROM oauth_scopes WHERE oauth_scopes.key = :scope
|
||||
* </code>
|
||||
*
|
||||
* Response:
|
||||
*
|
||||
* <code>
|
||||
* Array
|
||||
* (
|
||||
* [id] => (int) The scope's ID
|
||||
* [key] => (string) The scope itself
|
||||
* [name] => (string) The scope's name
|
||||
* [description] => (string) The scope's description
|
||||
* )
|
||||
* </code>
|
||||
*
|
||||
* @param string $scope The scope
|
||||
* @param string $clientId The client ID
|
||||
* @param string $grantType The grant type used in the request
|
||||
* @return bool|array If the scope doesn't exist return false
|
||||
*/
|
||||
public function getScope($scope, $clientId = null, $grantType = null);
|
||||
}
|
@@ -1,272 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* OAuth 2.0 Session storage interface
|
||||
*
|
||||
* @package php-loep/oauth2-server
|
||||
* @author Alex Bilbie <hello@alexbilbie.com>
|
||||
* @copyright Copyright (c) 2013 PHP League of Extraordinary Packages
|
||||
* @license http://mit-license.org/
|
||||
* @link http://github.com/php-loep/oauth2-server
|
||||
*/
|
||||
|
||||
namespace League\OAuth2\Server\Storage;
|
||||
|
||||
interface SessionInterface
|
||||
{
|
||||
/**
|
||||
* Create a new session
|
||||
*
|
||||
* Example SQL query:
|
||||
*
|
||||
* <code>
|
||||
* INSERT INTO oauth_sessions (client_id, owner_type, owner_id)
|
||||
* VALUE (:clientId, :ownerType, :ownerId)
|
||||
* </code>
|
||||
*
|
||||
* @param string $clientId The client ID
|
||||
* @param string $ownerType The type of the session owner (e.g. "user")
|
||||
* @param string $ownerId The ID of the session owner (e.g. "123")
|
||||
* @return int The session ID
|
||||
*/
|
||||
public function createSession($clientId, $ownerType, $ownerId);
|
||||
|
||||
/**
|
||||
* Delete a session
|
||||
*
|
||||
* Example SQL query:
|
||||
*
|
||||
* <code>
|
||||
* DELETE FROM oauth_sessions WHERE client_id = :clientId AND owner_type = :type AND owner_id = :typeId
|
||||
* </code>
|
||||
*
|
||||
* @param string $clientId The client ID
|
||||
* @param string $ownerType The type of the session owner (e.g. "user")
|
||||
* @param string $ownerId The ID of the session owner (e.g. "123")
|
||||
* @return void
|
||||
*/
|
||||
public function deleteSession($clientId, $ownerType, $ownerId);
|
||||
|
||||
/**
|
||||
* Associate a redirect URI with a session
|
||||
*
|
||||
* Example SQL query:
|
||||
*
|
||||
* <code>
|
||||
* INSERT INTO oauth_session_redirects (session_id, redirect_uri) VALUE (:sessionId, :redirectUri)
|
||||
* </code>
|
||||
*
|
||||
* @param int $sessionId The session ID
|
||||
* @param string $redirectUri The redirect URI
|
||||
* @return void
|
||||
*/
|
||||
public function associateRedirectUri($sessionId, $redirectUri);
|
||||
|
||||
/**
|
||||
* Associate an access token with a session
|
||||
*
|
||||
* Example SQL query:
|
||||
*
|
||||
* <code>
|
||||
* INSERT INTO oauth_session_access_tokens (session_id, access_token, access_token_expires)
|
||||
* VALUE (:sessionId, :accessToken, :accessTokenExpire)
|
||||
* </code>
|
||||
*
|
||||
* @param int $sessionId The session ID
|
||||
* @param string $accessToken The access token
|
||||
* @param int $expireTime Unix timestamp of the access token expiry time
|
||||
* @return void
|
||||
*/
|
||||
public function associateAccessToken($sessionId, $accessToken, $expireTime);
|
||||
|
||||
/**
|
||||
* Associate a refresh token with a session
|
||||
*
|
||||
* Example SQL query:
|
||||
*
|
||||
* <code>
|
||||
* oauth_session_refresh_tokens (session_access_token_id, refresh_token, refresh_token_expires)
|
||||
* VALUE (:accessTokenId, :refreshToken, :expireTime)
|
||||
* </code>
|
||||
*
|
||||
* @param int $accessTokenId The access token ID
|
||||
* @param string $refreshToken The refresh token
|
||||
* @param int $expireTime Unix timestamp of the refresh token expiry time
|
||||
* @return void
|
||||
*/
|
||||
public function associateRefreshToken($accessTokenId, $refreshToken, $expireTime);
|
||||
|
||||
/**
|
||||
* Assocate an authorization code with a session
|
||||
*
|
||||
* Example SQL query:
|
||||
*
|
||||
* <code>
|
||||
* INSERT INTO oauth_session_authcodes (session_id, auth_code, auth_code_expires, scope_ids)
|
||||
* VALUE (:sessionId, :authCode, :authCodeExpires, :scopeIds)
|
||||
* </code>
|
||||
*
|
||||
* @param int $sessionId The session ID
|
||||
* @param string $authCode The authorization code
|
||||
* @param int $expireTime Unix timestamp of the access token expiry time
|
||||
* @param string $scopeIds Comma seperated list of scope IDs to be later associated (default = null)
|
||||
* @return void
|
||||
*/
|
||||
public function associateAuthCode($sessionId, $authCode, $expireTime, $scopeIds = null);
|
||||
|
||||
/**
|
||||
* Remove an associated authorization token from a session
|
||||
*
|
||||
* Example SQL query:
|
||||
*
|
||||
* <code>
|
||||
* DELETE FROM oauth_session_authcodes WHERE session_id = :sessionId
|
||||
* </code>
|
||||
*
|
||||
* @param int $sessionId The session ID
|
||||
* @return void
|
||||
*/
|
||||
public function removeAuthCode($sessionId);
|
||||
|
||||
/**
|
||||
* Validate an authorization code
|
||||
*
|
||||
* Example SQL query:
|
||||
*
|
||||
* <code>
|
||||
* SELECT oauth_sessions.id, oauth_session_authcodes.scope_ids FROM oauth_sessions
|
||||
* JOIN oauth_session_authcodes ON oauth_session_authcodes.`session_id` = oauth_sessions.id
|
||||
* JOIN oauth_session_redirects ON oauth_session_redirects.`session_id` = oauth_sessions.id WHERE
|
||||
* oauth_sessions.client_id = :clientId AND oauth_session_authcodes.`auth_code` = :authCode
|
||||
* AND `oauth_session_authcodes`.`auth_code_expires` >= :time AND
|
||||
* `oauth_session_redirects`.`redirect_uri` = :redirectUri
|
||||
* </code>
|
||||
*
|
||||
* Expected response:
|
||||
*
|
||||
* <code>
|
||||
* array(
|
||||
* 'id' => (int), // the session ID
|
||||
* 'scope_ids' => (string)
|
||||
* )
|
||||
* </code>
|
||||
*
|
||||
* @param string $clientId The client ID
|
||||
* @param string $redirectUri The redirect URI
|
||||
* @param string $authCode The authorization code
|
||||
* @return array|bool False if invalid or array as above
|
||||
*/
|
||||
public function validateAuthCode($clientId, $redirectUri, $authCode);
|
||||
|
||||
/**
|
||||
* Validate an access token
|
||||
*
|
||||
* Example SQL query:
|
||||
*
|
||||
* <code>
|
||||
* SELECT session_id, oauth_sessions.`client_id`, oauth_sessions.`owner_id`, oauth_sessions.`owner_type`
|
||||
* FROM `oauth_session_access_tokens` JOIN oauth_sessions ON oauth_sessions.`id` = session_id WHERE
|
||||
* access_token = :accessToken AND access_token_expires >= UNIX_TIMESTAMP(NOW())
|
||||
* </code>
|
||||
*
|
||||
* Expected response:
|
||||
*
|
||||
* <code>
|
||||
* array(
|
||||
* 'session_id' => (int),
|
||||
* 'client_id' => (string),
|
||||
* 'owner_id' => (string),
|
||||
* 'owner_type' => (string)
|
||||
* )
|
||||
* </code>
|
||||
*
|
||||
* @param string $accessToken The access token
|
||||
* @return array|bool False if invalid or an array as above
|
||||
*/
|
||||
public function validateAccessToken($accessToken);
|
||||
|
||||
/**
|
||||
* Validate a refresh token
|
||||
*
|
||||
* Example SQL query:
|
||||
*
|
||||
* <code>
|
||||
* SELECT session_access_token_id FROM `oauth_session_refresh_tokens` WHERE refresh_token = :refreshToken
|
||||
* AND refresh_token_expires >= UNIX_TIMESTAMP(NOW())
|
||||
* </code>
|
||||
*
|
||||
* @param string $refreshToken The access token
|
||||
* @return int|bool The ID of the access token the refresh token is linked to (or false if invalid)
|
||||
*/
|
||||
public function validateRefreshToken($refreshToken);
|
||||
|
||||
/**
|
||||
* Get an access token by ID
|
||||
*
|
||||
* Example SQL query:
|
||||
*
|
||||
* <code>
|
||||
* SELECT * FROM `oauth_session_access_tokens` WHERE `id` = :accessTokenId
|
||||
* </code>
|
||||
*
|
||||
* Expected response:
|
||||
*
|
||||
* <code>
|
||||
* array(
|
||||
* 'id' => (int),
|
||||
* 'session_id' => (int),
|
||||
* 'access_token' => (string),
|
||||
* 'access_token_expires' => (int)
|
||||
* )
|
||||
* </code>
|
||||
*
|
||||
* @param int $accessTokenId The access token ID
|
||||
* @return array
|
||||
*/
|
||||
public function getAccessToken($accessTokenId);
|
||||
|
||||
/**
|
||||
* Associate a scope with an access token
|
||||
*
|
||||
* Example SQL query:
|
||||
*
|
||||
* <code>
|
||||
* INSERT INTO `oauth_session_token_scopes` (`session_access_token_id`, `scope_id`) VALUE (:accessTokenId, :scopeId)
|
||||
* </code>
|
||||
*
|
||||
* @param int $accessTokenId The ID of the access token
|
||||
* @param int $scopeId The ID of the scope
|
||||
* @return void
|
||||
*/
|
||||
public function associateScope($accessTokenId, $scopeId);
|
||||
|
||||
/**
|
||||
* Get all associated access tokens for an access token
|
||||
*
|
||||
* Example SQL query:
|
||||
*
|
||||
* <code>
|
||||
* SELECT oauth_scopes.* FROM oauth_session_token_scopes JOIN oauth_session_access_tokens
|
||||
* ON oauth_session_access_tokens.`id` = `oauth_session_token_scopes`.`session_access_token_id`
|
||||
* JOIN oauth_scopes ON oauth_scopes.id = `oauth_session_token_scopes`.`scope_id`
|
||||
* WHERE access_token = :accessToken
|
||||
* </code>
|
||||
*
|
||||
* Expected response:
|
||||
*
|
||||
* <code>
|
||||
* array (
|
||||
* array(
|
||||
* 'key' => (string),
|
||||
* 'name' => (string),
|
||||
* 'description' => (string)
|
||||
* ),
|
||||
* ...
|
||||
* ...
|
||||
* )
|
||||
* </code>
|
||||
*
|
||||
* @param string $accessToken The access token
|
||||
* @return array
|
||||
*/
|
||||
public function getScopes($accessToken);
|
||||
}
|
@@ -1,31 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* OAuth 2.0 Redirect URI generator
|
||||
*
|
||||
* @package php-loep/oauth2-server
|
||||
* @author Alex Bilbie <hello@alexbilbie.com>
|
||||
* @copyright Copyright (c) 2013 PHP League of Extraordinary Packages
|
||||
* @license http://mit-license.org/
|
||||
* @link http://github.com/php-loep/oauth2-server
|
||||
*/
|
||||
|
||||
namespace League\OAuth2\Server\Util;
|
||||
|
||||
/**
|
||||
* RedirectUri class
|
||||
*/
|
||||
class RedirectUri
|
||||
{
|
||||
/**
|
||||
* Generate a new redirect uri
|
||||
* @param string $uri The base URI
|
||||
* @param array $params The query string parameters
|
||||
* @param string $queryDelimeter The query string delimeter (default: "?")
|
||||
* @return string The updated URI
|
||||
*/
|
||||
public static function make($uri, $params = array(), $queryDelimeter = '?')
|
||||
{
|
||||
$uri .= (strstr($uri, $queryDelimeter) === false) ? $queryDelimeter : '&';
|
||||
return $uri.http_build_query($params);
|
||||
}
|
||||
}
|
@@ -1,109 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* OAuth 2.0 Request class
|
||||
*
|
||||
* @package php-loep/oauth2-server
|
||||
* @author Alex Bilbie <hello@alexbilbie.com>
|
||||
* @copyright Copyright (c) 2013 PHP League of Extraordinary Packages
|
||||
* @license http://mit-license.org/
|
||||
* @link http://github.com/php-loep/oauth2-server
|
||||
*/
|
||||
|
||||
namespace League\OAuth2\Server\Util;
|
||||
|
||||
use OutOfBoundsException;
|
||||
use InvalidMethodCallException;
|
||||
use InvalidArgumentException;
|
||||
|
||||
class Request implements RequestInterface
|
||||
{
|
||||
protected $get = array();
|
||||
protected $post = array();
|
||||
protected $cookies = array();
|
||||
protected $files = array();
|
||||
protected $server = array();
|
||||
protected $headers = array();
|
||||
|
||||
public static function buildFromGlobals()
|
||||
{
|
||||
return new static($_GET, $_POST, $_COOKIE, $_FILES, $_SERVER);
|
||||
}
|
||||
|
||||
public function __construct(array $get = array(), array $post = array(), array $cookies = array(), array $files = array(), array $server = array(), $headers = array())
|
||||
{
|
||||
$this->get = $get;
|
||||
$this->post = $post;
|
||||
$this->cookies = $cookies;
|
||||
$this->files = $files;
|
||||
$this->server = $server;
|
||||
|
||||
if (empty($headers)) {
|
||||
$this->headers = $this->readHeaders();
|
||||
}
|
||||
}
|
||||
|
||||
public function get($index = null, $default = null)
|
||||
{
|
||||
return $this->getPropertyValue('get', $index, $default);
|
||||
}
|
||||
|
||||
public function post($index = null, $default = null)
|
||||
{
|
||||
return $this->getPropertyValue('post', $index, $default);
|
||||
}
|
||||
|
||||
public function file($index = null, $default = null)
|
||||
{
|
||||
return $this->getPropertyValue('files', $index, $default);
|
||||
}
|
||||
|
||||
public function cookie($index = null, $default = null)
|
||||
{
|
||||
return $this->getPropertyValue('cookies', $index, $default);
|
||||
}
|
||||
|
||||
public function server($index = null, $default = null)
|
||||
{
|
||||
return $this->getPropertyValue('server', $index, $default);
|
||||
}
|
||||
|
||||
public function header($index = null, $default = null)
|
||||
{
|
||||
return $this->getPropertyValue('headers', $index, $default);
|
||||
}
|
||||
|
||||
protected function readHeaders()
|
||||
{
|
||||
if (function_exists('getallheaders')) {
|
||||
// @codeCoverageIgnoreStart
|
||||
$headers = getallheaders();
|
||||
} else {
|
||||
// @codeCoverageIgnoreEnd
|
||||
$headers = array();
|
||||
foreach ($this->server() as $name => $value) {
|
||||
if (substr($name, 0, 5) == 'HTTP_') {
|
||||
$name = str_replace(' ', '-', ucwords(strtolower(str_replace('_', ' ', substr($name, 5)))));
|
||||
$headers[$name] = $value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $headers;
|
||||
}
|
||||
|
||||
protected function getPropertyValue($property, $index = null, $default = null)
|
||||
{
|
||||
if ( ! isset($this->{$property})) {
|
||||
throw new InvalidArgumentException("Property '$property' does not exist.");
|
||||
}
|
||||
if (is_null($index)) {
|
||||
return $this->{$property};
|
||||
}
|
||||
|
||||
if ( ! array_key_exists($index, $this->{$property})) {
|
||||
return $default;
|
||||
}
|
||||
|
||||
return $this->{$property}[$index];
|
||||
}
|
||||
}
|
@@ -1,33 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* OAuth 2.0 Request class interface
|
||||
*
|
||||
* @package php-loep/oauth2-server
|
||||
* @author Alex Bilbie <hello@alexbilbie.com>
|
||||
* @copyright Copyright (c) 2013 PHP League of Extraordinary Packages
|
||||
* @license http://mit-license.org/
|
||||
* @link http://github.com/php-loep/oauth2-server
|
||||
*/
|
||||
|
||||
namespace League\OAuth2\Server\Util;
|
||||
|
||||
interface RequestInterface
|
||||
{
|
||||
|
||||
public static function buildFromGlobals();
|
||||
|
||||
public function __construct(array $get = array(), array $post = array(), array $cookies = array(), array $files = array(), array $server = array(), $headers = array());
|
||||
|
||||
public function get($index = null);
|
||||
|
||||
public function post($index = null);
|
||||
|
||||
public function cookie($index = null);
|
||||
|
||||
public function file($index = null);
|
||||
|
||||
public function server($index = null);
|
||||
|
||||
public function header($index = null);
|
||||
|
||||
}
|
@@ -1,40 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* OAuth 2.0 Secure key generator
|
||||
*
|
||||
* @package php-loep/oauth2-server
|
||||
* @author Alex Bilbie <hello@alexbilbie.com>
|
||||
* @copyright Copyright (c) 2013 PHP League of Extraordinary Packages
|
||||
* @license http://mit-license.org/
|
||||
* @link http://github.com/php-loep/oauth2-server
|
||||
*/
|
||||
|
||||
namespace League\OAuth2\Server\Util;
|
||||
|
||||
/**
|
||||
* SecureKey class
|
||||
*/
|
||||
class SecureKey
|
||||
{
|
||||
/**
|
||||
* Generate a new unique code
|
||||
* @param integer $len Length of the generated code
|
||||
* @return string
|
||||
*/
|
||||
public static function make($len = 40)
|
||||
{
|
||||
// We generate twice as many bytes here because we want to ensure we have
|
||||
// enough after we base64 encode it to get the length we need because we
|
||||
// take out the "/", "+", and "=" characters.
|
||||
$bytes = openssl_random_pseudo_bytes($len * 2, $strong);
|
||||
|
||||
// We want to stop execution if the key fails because, well, that is bad.
|
||||
if ($bytes === false || $strong === false) {
|
||||
// @codeCoverageIgnoreStart
|
||||
throw new \Exception('Error Generating Key');
|
||||
// @codeCoverageIgnoreEnd
|
||||
}
|
||||
|
||||
return substr(str_replace(array('/', '+', '='), '', base64_encode($bytes)), 0, $len);
|
||||
}
|
||||
}
|
58
src/Middleware/AuthorizationServerMiddleware.php
Normal file
58
src/Middleware/AuthorizationServerMiddleware.php
Normal file
@@ -0,0 +1,58 @@
|
||||
<?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 \League\OAuth2\Server\AuthorizationServer
|
||||
*/
|
||||
private $server;
|
||||
|
||||
/**
|
||||
* AuthorizationServerMiddleware constructor.
|
||||
*
|
||||
* @param \League\OAuth2\Server\AuthorizationServer $server
|
||||
*/
|
||||
public function __construct(AuthorizationServer $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->respondToAccessTokenRequest($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);
|
||||
}
|
||||
}
|
58
src/Middleware/ResourceServerMiddleware.php
Normal file
58
src/Middleware/ResourceServerMiddleware.php
Normal file
@@ -0,0 +1,58 @@
|
||||
<?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\ResourceServer;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
use Psr\Http\Message\ServerRequestInterface;
|
||||
|
||||
class ResourceServerMiddleware
|
||||
{
|
||||
/**
|
||||
* @var \League\OAuth2\Server\ResourceServer
|
||||
*/
|
||||
private $server;
|
||||
|
||||
/**
|
||||
* ResourceServerMiddleware constructor.
|
||||
*
|
||||
* @param \League\OAuth2\Server\ResourceServer $server
|
||||
*/
|
||||
public function __construct(ResourceServer $server)
|
||||
{
|
||||
$this->server = $server;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \Psr\Http\Message\ServerRequestInterface $request
|
||||
* @param \Psr\Http\Message\ResponseInterface $response
|
||||
* @param callable $next
|
||||
*
|
||||
* @return \Psr\Http\Message\ResponseInterface
|
||||
*/
|
||||
public function __invoke(ServerRequestInterface $request, ResponseInterface $response, callable $next)
|
||||
{
|
||||
try {
|
||||
$request = $this->server->validateAuthenticatedRequest($request);
|
||||
} catch (OAuthServerException $exception) {
|
||||
return $exception->generateHttpResponse($response);
|
||||
// @codeCoverageIgnoreStart
|
||||
} catch (\Exception $exception) {
|
||||
$response->getBody()->write($exception->getMessage());
|
||||
|
||||
return $response->withStatus(500);
|
||||
// @codeCoverageIgnoreEnd
|
||||
}
|
||||
|
||||
// Pass the request and response on to the next responder in the chain
|
||||
return $next($request, $response);
|
||||
}
|
||||
}
|
53
src/Repositories/AccessTokenRepositoryInterface.php
Normal file
53
src/Repositories/AccessTokenRepositoryInterface.php
Normal file
@@ -0,0 +1,53 @@
|
||||
<?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\AccessTokenEntityInterface;
|
||||
use League\OAuth2\Server\Entities\ClientEntityInterface;
|
||||
|
||||
/**
|
||||
* Access token interface.
|
||||
*/
|
||||
interface AccessTokenRepositoryInterface extends RepositoryInterface
|
||||
{
|
||||
/**
|
||||
* Create a new access token
|
||||
*
|
||||
* @param \League\OAuth2\Server\Entities\ClientEntityInterface $clientEntity
|
||||
* @param \League\OAuth2\Server\Entities\ScopeEntityInterface[] $scopes
|
||||
* @param mixed $userIdentifier
|
||||
*
|
||||
* @return AccessTokenEntityInterface
|
||||
*/
|
||||
public function getNewToken(ClientEntityInterface $clientEntity, array $scopes, $userIdentifier = null);
|
||||
|
||||
/**
|
||||
* Persists a new access token to permanent storage.
|
||||
*
|
||||
* @param \League\OAuth2\Server\Entities\AccessTokenEntityInterface $accessTokenEntity
|
||||
*/
|
||||
public function persistNewAccessToken(AccessTokenEntityInterface $accessTokenEntity);
|
||||
|
||||
/**
|
||||
* Revoke an access token.
|
||||
*
|
||||
* @param string $tokenId
|
||||
*/
|
||||
public function revokeAccessToken($tokenId);
|
||||
|
||||
/**
|
||||
* Check if the access token has been revoked.
|
||||
*
|
||||
* @param string $tokenId
|
||||
*
|
||||
* @return bool Return true if this token has been revoked
|
||||
*/
|
||||
public function isAccessTokenRevoked($tokenId);
|
||||
}
|
47
src/Repositories/AuthCodeRepositoryInterface.php
Normal file
47
src/Repositories/AuthCodeRepositoryInterface.php
Normal file
@@ -0,0 +1,47 @@
|
||||
<?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\AuthCodeEntityInterface;
|
||||
|
||||
/**
|
||||
* Auth code storage interface.
|
||||
*/
|
||||
interface AuthCodeRepositoryInterface extends RepositoryInterface
|
||||
{
|
||||
/**
|
||||
* Creates a new AuthCode
|
||||
*
|
||||
* @return \League\OAuth2\Server\Entities\AuthCodeEntityInterface
|
||||
*/
|
||||
public function getNewAuthCode();
|
||||
|
||||
/**
|
||||
* Persists a new auth code to permanent storage.
|
||||
*
|
||||
* @param \League\OAuth2\Server\Entities\AuthCodeEntityInterface $authCodeEntity
|
||||
*/
|
||||
public function persistNewAuthCode(AuthCodeEntityInterface $authCodeEntity);
|
||||
|
||||
/**
|
||||
* Revoke an auth code.
|
||||
*
|
||||
* @param string $codeId
|
||||
*/
|
||||
public function revokeAuthCode($codeId);
|
||||
|
||||
/**
|
||||
* Check if the auth code has been revoked.
|
||||
*
|
||||
* @param string $codeId
|
||||
*
|
||||
* @return bool Return true if this code has been revoked
|
||||
*/
|
||||
public function isAuthCodeRevoked($codeId);
|
||||
}
|
28
src/Repositories/ClientRepositoryInterface.php
Normal file
28
src/Repositories/ClientRepositoryInterface.php
Normal file
@@ -0,0 +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;
|
||||
|
||||
/**
|
||||
* Client storage interface.
|
||||
*/
|
||||
interface ClientRepositoryInterface extends RepositoryInterface
|
||||
{
|
||||
/**
|
||||
* Get a client.
|
||||
*
|
||||
* @param string $clientIdentifier The client's identifier
|
||||
* @param string $grantType The grant type used
|
||||
* @param null|string $clientSecret The client's secret (if sent)
|
||||
* @param bool $mustValidateSecret If true the client must attempt to validate the secret unless the client
|
||||
* is confidential
|
||||
*
|
||||
* @return \League\OAuth2\Server\Entities\ClientEntityInterface
|
||||
*/
|
||||
public function getClientEntity($clientIdentifier, $grantType, $clientSecret = null, $mustValidateSecret = true);
|
||||
}
|
47
src/Repositories/RefreshTokenRepositoryInterface.php
Normal file
47
src/Repositories/RefreshTokenRepositoryInterface.php
Normal file
@@ -0,0 +1,47 @@
|
||||
<?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\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\RefreshTokenEntityInterface $refreshTokenEntity
|
||||
*/
|
||||
public function persistNewRefreshToken(RefreshTokenEntityInterface $refreshTokenEntity);
|
||||
|
||||
/**
|
||||
* Revoke the refresh token.
|
||||
*
|
||||
* @param string $tokenId
|
||||
*/
|
||||
public function revokeRefreshToken($tokenId);
|
||||
|
||||
/**
|
||||
* Check if the refresh token has been revoked.
|
||||
*
|
||||
* @param string $tokenId
|
||||
*
|
||||
* @return bool Return true if this token has been revoked
|
||||
*/
|
||||
public function isRefreshTokenRevoked($tokenId);
|
||||
}
|
16
src/Repositories/RepositoryInterface.php
Normal file
16
src/Repositories/RepositoryInterface.php
Normal file
@@ -0,0 +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\Repositories;
|
||||
|
||||
/**
|
||||
* Repository interface.
|
||||
*/
|
||||
interface RepositoryInterface
|
||||
{
|
||||
}
|
46
src/Repositories/ScopeRepositoryInterface.php
Normal file
46
src/Repositories/ScopeRepositoryInterface.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\Repositories;
|
||||
|
||||
use League\OAuth2\Server\Entities\ClientEntityInterface;
|
||||
use League\OAuth2\Server\Entities\ScopeEntityInterface;
|
||||
|
||||
/**
|
||||
* Scope interface.
|
||||
*/
|
||||
interface ScopeRepositoryInterface extends RepositoryInterface
|
||||
{
|
||||
/**
|
||||
* Return information about a scope.
|
||||
*
|
||||
* @param string $identifier The scope identifier
|
||||
*
|
||||
* @return \League\OAuth2\Server\Entities\ScopeEntityInterface
|
||||
*/
|
||||
public function getScopeEntityByIdentifier($identifier);
|
||||
|
||||
/**
|
||||
* 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\ClientEntityInterface $clientEntity
|
||||
* @param null|string $userIdentifier
|
||||
*
|
||||
* @return \League\OAuth2\Server\Entities\ScopeEntityInterface[]
|
||||
*/
|
||||
public function finalizeScopes(
|
||||
array $scopes,
|
||||
$grantType,
|
||||
ClientEntityInterface $clientEntity,
|
||||
$userIdentifier = null
|
||||
);
|
||||
}
|
32
src/Repositories/UserRepositoryInterface.php
Normal file
32
src/Repositories/UserRepositoryInterface.php
Normal file
@@ -0,0 +1,32 @@
|
||||
<?php
|
||||
/**
|
||||
* @author Alex Bilbie <hello@alexbilbie.com>
|
||||
* @copyright Copyright (c) Alex Bilbie
|
||||
* @license http://mit-license.org/
|
||||
*
|
||||
* @link https://github.com/thephpleague/oauth2-server
|
||||
*/
|
||||
|
||||
namespace League\OAuth2\Server\Repositories;
|
||||
|
||||
use League\OAuth2\Server\Entities\ClientEntityInterface;
|
||||
|
||||
interface UserRepositoryInterface extends RepositoryInterface
|
||||
{
|
||||
/**
|
||||
* Get a user entity.
|
||||
*
|
||||
* @param string $username
|
||||
* @param string $password
|
||||
* @param string $grantType The grant type used
|
||||
* @param \League\OAuth2\Server\Entities\ClientEntityInterface $clientEntity
|
||||
*
|
||||
* @return \League\OAuth2\Server\Entities\UserEntityInterface
|
||||
*/
|
||||
public function getUserEntityByUserCredentials(
|
||||
$username,
|
||||
$password,
|
||||
$grantType,
|
||||
ClientEntityInterface $clientEntity
|
||||
);
|
||||
}
|
41
src/RequestEvent.php
Normal file
41
src/RequestEvent.php
Normal file
@@ -0,0 +1,41 @@
|
||||
<?php
|
||||
/**
|
||||
* @author Alex Bilbie <hello@alexbilbie.com>
|
||||
* @copyright Copyright (c) Alex Bilbie
|
||||
* @license http://mit-license.org/
|
||||
*
|
||||
* @link https://github.com/thephpleague/oauth2-server
|
||||
*/
|
||||
namespace League\OAuth2\Server;
|
||||
|
||||
use League\Event\Event;
|
||||
use Psr\Http\Message\ServerRequestInterface;
|
||||
|
||||
class RequestEvent extends Event
|
||||
{
|
||||
/**
|
||||
* @var \Psr\Http\Message\ServerRequestInterface
|
||||
*/
|
||||
private $request;
|
||||
|
||||
/**
|
||||
* RequestEvent constructor.
|
||||
*
|
||||
* @param string $name
|
||||
* @param \Psr\Http\Message\ServerRequestInterface $request
|
||||
*/
|
||||
public function __construct($name, ServerRequestInterface $request)
|
||||
{
|
||||
parent::__construct($name);
|
||||
$this->request = $request;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return ServerRequestInterface
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public function getRequest()
|
||||
{
|
||||
return $this->request;
|
||||
}
|
||||
}
|
178
src/RequestTypes/AuthorizationRequest.php
Normal file
178
src/RequestTypes/AuthorizationRequest.php
Normal file
@@ -0,0 +1,178 @@
|
||||
<?php
|
||||
/**
|
||||
* @author Alex Bilbie <hello@alexbilbie.com>
|
||||
* @copyright Copyright (c) Alex Bilbie
|
||||
* @license http://mit-license.org/
|
||||
*
|
||||
* @link https://github.com/thephpleague/oauth2-server
|
||||
*/
|
||||
|
||||
namespace League\OAuth2\Server\RequestTypes;
|
||||
|
||||
use League\OAuth2\Server\Entities\ClientEntityInterface;
|
||||
use League\OAuth2\Server\Entities\ScopeEntityInterface;
|
||||
use League\OAuth2\Server\Entities\UserEntityInterface;
|
||||
|
||||
class AuthorizationRequest
|
||||
{
|
||||
/**
|
||||
* The grant type identifier
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $grantTypeId;
|
||||
|
||||
/**
|
||||
* The client identifier
|
||||
*
|
||||
* @var ClientEntityInterface
|
||||
*/
|
||||
protected $client;
|
||||
|
||||
/**
|
||||
* The user identifier
|
||||
*
|
||||
* @var UserEntityInterface
|
||||
*/
|
||||
protected $user;
|
||||
|
||||
/**
|
||||
* An array of scope identifiers
|
||||
*
|
||||
* @var ScopeEntityInterface[]
|
||||
*/
|
||||
protected $scopes = [];
|
||||
|
||||
/**
|
||||
* Has the user authorized the authorization request
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
protected $authorizationApproved = false;
|
||||
|
||||
/**
|
||||
* The redirect URI used in the request
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $redirectUri;
|
||||
|
||||
/**
|
||||
* The state parameter on the authorization request
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $state;
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getGrantTypeId()
|
||||
{
|
||||
return $this->grantTypeId;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $grantTypeId
|
||||
*/
|
||||
public function setGrantTypeId($grantTypeId)
|
||||
{
|
||||
$this->grantTypeId = $grantTypeId;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return ClientEntityInterface
|
||||
*/
|
||||
public function getClient()
|
||||
{
|
||||
return $this->client;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ClientEntityInterface $client
|
||||
*/
|
||||
public function setClient(ClientEntityInterface $client)
|
||||
{
|
||||
$this->client = $client;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return UserEntityInterface
|
||||
*/
|
||||
public function getUser()
|
||||
{
|
||||
return $this->user;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param UserEntityInterface $user
|
||||
*/
|
||||
public function setUser(UserEntityInterface $user)
|
||||
{
|
||||
$this->user = $user;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \League\OAuth2\Server\Entities\ScopeEntityInterface[]
|
||||
*/
|
||||
public function getScopes()
|
||||
{
|
||||
return $this->scopes;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \League\OAuth2\Server\Entities\ScopeEntityInterface[] $scopes
|
||||
*/
|
||||
public function setScopes($scopes)
|
||||
{
|
||||
$this->scopes = $scopes;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function isAuthorizationApproved()
|
||||
{
|
||||
return $this->authorizationApproved;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param bool $authorizationApproved
|
||||
*/
|
||||
public function setAuthorizationApproved($authorizationApproved)
|
||||
{
|
||||
$this->authorizationApproved = $authorizationApproved;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getRedirectUri()
|
||||
{
|
||||
return $this->redirectUri;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $redirectUri
|
||||
*/
|
||||
public function setRedirectUri($redirectUri)
|
||||
{
|
||||
$this->redirectUri = $redirectUri;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getState()
|
||||
{
|
||||
return $this->state;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $state
|
||||
*/
|
||||
public function setState($state)
|
||||
{
|
||||
$this->state = $state;
|
||||
}
|
||||
}
|
80
src/ResourceServer.php
Normal file
80
src/ResourceServer.php
Normal file
@@ -0,0 +1,80 @@
|
||||
<?php
|
||||
/**
|
||||
* @author Alex Bilbie <hello@alexbilbie.com>
|
||||
* @copyright Copyright (c) Alex Bilbie
|
||||
* @license http://mit-license.org/
|
||||
*
|
||||
* @link https://github.com/thephpleague/oauth2-server
|
||||
*/
|
||||
namespace League\OAuth2\Server;
|
||||
|
||||
use League\OAuth2\Server\AuthorizationValidators\AuthorizationValidatorInterface;
|
||||
use League\OAuth2\Server\AuthorizationValidators\BearerTokenValidator;
|
||||
use League\OAuth2\Server\Repositories\AccessTokenRepositoryInterface;
|
||||
use Psr\Http\Message\ServerRequestInterface;
|
||||
|
||||
class ResourceServer
|
||||
{
|
||||
/**
|
||||
* @var \League\OAuth2\Server\Repositories\AccessTokenRepositoryInterface
|
||||
*/
|
||||
private $accessTokenRepository;
|
||||
/**
|
||||
* @var \League\OAuth2\Server\CryptKey|string
|
||||
*/
|
||||
private $publicKey;
|
||||
/**
|
||||
* @var \League\OAuth2\Server\AuthorizationValidators\AuthorizationValidatorInterface|null
|
||||
*/
|
||||
private $authorizationValidator;
|
||||
|
||||
/**
|
||||
* New server instance.
|
||||
*
|
||||
* @param \League\OAuth2\Server\Repositories\AccessTokenRepositoryInterface $accessTokenRepository
|
||||
* @param \League\OAuth2\Server\CryptKey|string $publicKey
|
||||
* @param null|\League\OAuth2\Server\AuthorizationValidators\AuthorizationValidatorInterface $authorizationValidator
|
||||
*/
|
||||
public function __construct(
|
||||
AccessTokenRepositoryInterface $accessTokenRepository,
|
||||
$publicKey,
|
||||
AuthorizationValidatorInterface $authorizationValidator = null
|
||||
) {
|
||||
$this->accessTokenRepository = $accessTokenRepository;
|
||||
|
||||
if (!$publicKey instanceof CryptKey) {
|
||||
$publicKey = new CryptKey($publicKey);
|
||||
}
|
||||
$this->publicKey = $publicKey;
|
||||
|
||||
$this->authorizationValidator = $authorizationValidator;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \League\OAuth2\Server\AuthorizationValidators\AuthorizationValidatorInterface
|
||||
*/
|
||||
protected function getAuthorizationValidator()
|
||||
{
|
||||
if (!$this->authorizationValidator instanceof AuthorizationValidatorInterface) {
|
||||
$this->authorizationValidator = new BearerTokenValidator($this->accessTokenRepository);
|
||||
}
|
||||
|
||||
$this->authorizationValidator->setPublicKey($this->publicKey);
|
||||
|
||||
return $this->authorizationValidator;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine the access token validity.
|
||||
*
|
||||
* @param \Psr\Http\Message\ServerRequestInterface $request
|
||||
*
|
||||
* @throws \League\OAuth2\Server\Exception\OAuthServerException
|
||||
*
|
||||
* @return \Psr\Http\Message\ServerRequestInterface
|
||||
*/
|
||||
public function validateAuthenticatedRequest(ServerRequestInterface $request)
|
||||
{
|
||||
return $this->getAuthorizationValidator()->validateAuthorization($request);
|
||||
}
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user