@@ -115,7 +115,7 @@ |
||
115 | 115 | </div> |
116 | 116 | <div id="rc-sidebar-accordion-payments" |
117 | 117 | class="panel-collapse collapse<?php echo in_array($view, array('payments', 'payment_configurations', 'payment_dashboards', 'payment_logs')) ? |
118 | - ' in' : '';?>"> |
|
118 | + ' in' : '';?>"> |
|
119 | 119 | <ul class="list-group"> |
120 | 120 | <li class="list-group-item"> |
121 | 121 | <a href="<?php echo JRoute::_('index.php?option=com_redcore&view=payment_dashboard') ?>"> |
@@ -41,21 +41,21 @@ |
||
41 | 41 | |
42 | 42 | class RDatabaseSqlparserLexersplitter { |
43 | 43 | |
44 | - private static $splitters = array("\r\n", "!=", ">=", "<=", "<>", ":=", "\\", "&&", ">", "<", "|", "=", "^", "(", |
|
45 | - ")", "\t", "\n", "'", "\"", "`", ",", "@", " ", "+", "-", "*", "/", ";"); |
|
46 | - private $tokenSize; |
|
47 | - private $hashSet; |
|
44 | + private static $splitters = array("\r\n", "!=", ">=", "<=", "<>", ":=", "\\", "&&", ">", "<", "|", "=", "^", "(", |
|
45 | + ")", "\t", "\n", "'", "\"", "`", ",", "@", " ", "+", "-", "*", "/", ";"); |
|
46 | + private $tokenSize; |
|
47 | + private $hashSet; |
|
48 | 48 | |
49 | - public function __construct() { |
|
50 | - $this->tokenSize = strlen(self::$splitters[0]); # should be the largest one |
|
51 | - $this->hashSet = array_flip(self::$splitters); |
|
52 | - } |
|
49 | + public function __construct() { |
|
50 | + $this->tokenSize = strlen(self::$splitters[0]); # should be the largest one |
|
51 | + $this->hashSet = array_flip(self::$splitters); |
|
52 | + } |
|
53 | 53 | |
54 | - public function getMaxLengthOfSplitter() { |
|
55 | - return $this->tokenSize; |
|
56 | - } |
|
54 | + public function getMaxLengthOfSplitter() { |
|
55 | + return $this->tokenSize; |
|
56 | + } |
|
57 | 57 | |
58 | - public function isSplitter($token) { |
|
59 | - return isset($this->hashSet[$token]); |
|
60 | - } |
|
58 | + public function isSplitter($token) { |
|
59 | + return isset($this->hashSet[$token]); |
|
60 | + } |
|
61 | 61 | } |
@@ -141,18 +141,18 @@ |
||
141 | 141 | 'UTC_TIME', 'UTC_TIMESTAMP', 'UUID', 'VAR_POP', 'VAR_SAMP', 'VARIANCE', |
142 | 142 | 'VERSION', 'WEEK', 'WEEKDAY', 'WEEKOFYEAR', 'YEAR', 'YEARWEEK'); |
143 | 143 | |
144 | - /** |
|
145 | - * Ends the given string $haystack with the string $needle? |
|
146 | - * @param string $haystack |
|
147 | - * @param string $needle |
|
148 | - */ |
|
149 | - protected function endsWith($haystack, $needle) { |
|
150 | - $length = strlen($needle); |
|
151 | - if ($length == 0) { |
|
152 | - return true; |
|
153 | - } |
|
144 | + /** |
|
145 | + * Ends the given string $haystack with the string $needle? |
|
146 | + * @param string $haystack |
|
147 | + * @param string $needle |
|
148 | + */ |
|
149 | + protected function endsWith($haystack, $needle) { |
|
150 | + $length = strlen($needle); |
|
151 | + if ($length == 0) { |
|
152 | + return true; |
|
153 | + } |
|
154 | 154 | |
155 | - $start = $length * -1; |
|
156 | - return (substr($haystack, $start) === $needle); |
|
157 | - } |
|
155 | + $start = $length * -1; |
|
156 | + return (substr($haystack, $start) === $needle); |
|
157 | + } |
|
158 | 158 | } |
@@ -49,164 +49,164 @@ |
||
49 | 49 | */ |
50 | 50 | class RDatabaseSqlparserPositioncalculator extends RDatabaseSqlparserSqlparserutils { |
51 | 51 | |
52 | - private static $allowedOnOperator = array("\t", "\n", "\r", " ", ",", "(", ")", "_", "'", "\""); |
|
53 | - private static $allowedOnOther = array("\t", "\n", "\r", " ", ",", "(", ")", "<", ">", "*", "+", "-", "/", "|", |
|
54 | - "&", "=", "!", ";"); |
|
55 | - |
|
56 | - private function printPos($text, $sql, $charPos, $key, $parsed, $backtracking) { |
|
57 | - if (!isset($_ENV['DEBUG'])) { |
|
58 | - return; |
|
59 | - } |
|
60 | - |
|
61 | - $spaces = ""; |
|
62 | - $caller = debug_backtrace(); |
|
63 | - $i = 1; |
|
64 | - while ($caller[$i]['function'] === 'lookForBaseExpression') { |
|
65 | - $spaces .= " "; |
|
66 | - $i++; |
|
67 | - } |
|
68 | - $holdem = substr($sql, 0, $charPos) . "^" . substr($sql, $charPos); |
|
69 | - echo $spaces . $text . " key:" . $key . " parsed:" . $parsed . " back:" . serialize($backtracking) . " " |
|
70 | - . $holdem . "\n"; |
|
71 | - } |
|
72 | - |
|
73 | - public function setPositionsWithinSQL($sql, $parsed) { |
|
74 | - $charPos = 0; |
|
75 | - $backtracking = array(); |
|
76 | - $this->lookForBaseExpression($sql, $charPos, $parsed, 0, $backtracking); |
|
77 | - return $parsed; |
|
78 | - } |
|
79 | - |
|
80 | - private function findPositionWithinString($sql, $value, $expr_type) { |
|
81 | - |
|
82 | - $offset = 0; |
|
83 | - while (true) { |
|
84 | - |
|
85 | - $pos = strpos($sql, $value, $offset); |
|
86 | - if ($pos === false) { |
|
87 | - break; |
|
88 | - } |
|
89 | - |
|
90 | - $before = ""; |
|
91 | - if ($pos > 0) { |
|
92 | - $before = $sql[$pos - 1]; |
|
93 | - } |
|
94 | - |
|
95 | - $after = ""; |
|
96 | - if (isset($sql[$pos + strlen($value)])) { |
|
97 | - $after = $sql[$pos + strlen($value)]; |
|
98 | - } |
|
99 | - |
|
100 | - // if we have an operator, it should be surrounded by |
|
101 | - // whitespace, comma, parenthesis, digit or letter, end_of_string |
|
102 | - // an operator should not be surrounded by another operator |
|
103 | - |
|
104 | - if ($expr_type === 'operator') { |
|
105 | - |
|
106 | - $ok = ($before === "" || in_array($before, self::$allowedOnOperator, true)) |
|
107 | - || (strtolower($before) >= 'a' && strtolower($before) <= 'z') |
|
108 | - || ($before >= '0' && $before <= '9'); |
|
109 | - $ok = $ok |
|
110 | - && ($after === "" || in_array($after, self::$allowedOnOperator, true) |
|
111 | - || (strtolower($after) >= 'a' && strtolower($after) <= 'z') |
|
112 | - || ($after >= '0' && $after <= '9') || ($after === '?') || ($after === '@')); |
|
113 | - |
|
114 | - if (!$ok) { |
|
115 | - $offset = $pos + 1; |
|
116 | - continue; |
|
117 | - } |
|
118 | - |
|
119 | - break; |
|
120 | - } |
|
121 | - |
|
122 | - // in all other cases we accept |
|
123 | - // whitespace, comma, operators, parenthesis and end_of_string |
|
124 | - |
|
125 | - $ok = ($before === "" || in_array($before, self::$allowedOnOther, true)); |
|
126 | - $ok = $ok && ($after === "" || in_array($after, self::$allowedOnOther, true)); |
|
127 | - |
|
128 | - if ($ok) { |
|
129 | - break; |
|
130 | - } |
|
131 | - |
|
132 | - $offset = $pos + 1; |
|
133 | - } |
|
134 | - |
|
135 | - return $pos; |
|
136 | - } |
|
137 | - |
|
138 | - private function lookForBaseExpression($sql, &$charPos, &$parsed, $key, &$backtracking) { |
|
139 | - if (!is_numeric($key)) { |
|
140 | - if (($key === 'UNION' || $key === 'UNION ALL') || ($key === 'expr_type' && $parsed === 'expression') |
|
141 | - || ($key === 'expr_type' && $parsed === 'subquery') |
|
142 | - || ($key === 'expr_type' && $parsed === 'bracket_expression') |
|
143 | - || ($key === 'expr_type' && $parsed === 'table_expression') |
|
144 | - || ($key === 'expr_type' && $parsed === 'record') |
|
145 | - || ($key === 'expr_type' && $parsed === 'in-list') || ($key === 'alias' && $parsed !== false)) { |
|
146 | - // we hold the current position and come back after the next base_expr |
|
147 | - // we do this, because the next base_expr contains the complete expression/subquery/record |
|
148 | - // and we have to look into it too |
|
149 | - $backtracking[] = $charPos; |
|
150 | - |
|
151 | - } elseif (($key === 'ref_clause' || $key === 'columns') && $parsed !== false) { |
|
152 | - // we hold the current position and come back after n base_expr(s) |
|
153 | - // there is an array of sub-elements before (!) the base_expr clause of the current element |
|
154 | - // so we go through the sub-elements and must come at the end |
|
155 | - $backtracking[] = $charPos; |
|
156 | - $parsedCount = count($parsed); |
|
157 | - for ($i = 1; $i < $parsedCount; $i++) { |
|
158 | - $backtracking[] = false; // backtracking only after n base_expr! |
|
159 | - } |
|
160 | - } elseif ($key === 'sub_tree' && $parsed !== false) { |
|
161 | - // we prevent wrong backtracking on subtrees (too much array_pop()) |
|
162 | - // there is an array of sub-elements after(!) the base_expr clause of the current element |
|
163 | - // so we go through the sub-elements and must not come back at the end |
|
164 | - $parsedCount = count($parsed); |
|
165 | - for ($i = 1; $i < $parsedCount; $i++) { |
|
166 | - $backtracking[] = false; |
|
167 | - } |
|
168 | - } else { |
|
169 | - // move the current pos after the keyword |
|
170 | - // SELECT, WHERE, INSERT etc. |
|
171 | - if (in_array($key, parent::$reserved)) { |
|
172 | - $charPos = stripos($sql, $key, $charPos); |
|
173 | - $charPos += strlen($key); |
|
174 | - } |
|
175 | - } |
|
176 | - } |
|
177 | - |
|
178 | - if (!is_array($parsed)) { |
|
179 | - return; |
|
180 | - } |
|
181 | - |
|
182 | - foreach ($parsed as $key => $value) { |
|
183 | - if ($key === 'base_expr') { |
|
184 | - |
|
185 | - // $this->printPos("0", $sql, $charPos, $key, $value, $backtracking); |
|
186 | - |
|
187 | - $subject = substr($sql, $charPos); |
|
188 | - $pos = $this->findPositionWithinString($subject, $value, |
|
189 | - isset($parsed['expr_type']) ? $parsed['expr_type'] : 'alias'); |
|
190 | - if ($pos === false) { |
|
191 | - throw new Exception("cannot calculate position of " . $value . " within " . $subject, 5); |
|
192 | - |
|
193 | - } |
|
194 | - |
|
195 | - $parsed['position'] = $charPos + $pos; |
|
196 | - $charPos += $pos + strlen($value); |
|
197 | - |
|
198 | - // $this->printPos("1", $sql, $charPos, $key, $value, $backtracking); |
|
199 | - |
|
200 | - $oldPos = array_pop($backtracking); |
|
201 | - if (isset($oldPos) && $oldPos !== false) { |
|
202 | - $charPos = $oldPos; |
|
203 | - } |
|
204 | - |
|
205 | - // $this->printPos("2", $sql, $charPos, $key, $value, $backtracking); |
|
206 | - |
|
207 | - } else { |
|
208 | - $this->lookForBaseExpression($sql, $charPos, $parsed[$key], $key, $backtracking); |
|
209 | - } |
|
210 | - } |
|
211 | - } |
|
52 | + private static $allowedOnOperator = array("\t", "\n", "\r", " ", ",", "(", ")", "_", "'", "\""); |
|
53 | + private static $allowedOnOther = array("\t", "\n", "\r", " ", ",", "(", ")", "<", ">", "*", "+", "-", "/", "|", |
|
54 | + "&", "=", "!", ";"); |
|
55 | + |
|
56 | + private function printPos($text, $sql, $charPos, $key, $parsed, $backtracking) { |
|
57 | + if (!isset($_ENV['DEBUG'])) { |
|
58 | + return; |
|
59 | + } |
|
60 | + |
|
61 | + $spaces = ""; |
|
62 | + $caller = debug_backtrace(); |
|
63 | + $i = 1; |
|
64 | + while ($caller[$i]['function'] === 'lookForBaseExpression') { |
|
65 | + $spaces .= " "; |
|
66 | + $i++; |
|
67 | + } |
|
68 | + $holdem = substr($sql, 0, $charPos) . "^" . substr($sql, $charPos); |
|
69 | + echo $spaces . $text . " key:" . $key . " parsed:" . $parsed . " back:" . serialize($backtracking) . " " |
|
70 | + . $holdem . "\n"; |
|
71 | + } |
|
72 | + |
|
73 | + public function setPositionsWithinSQL($sql, $parsed) { |
|
74 | + $charPos = 0; |
|
75 | + $backtracking = array(); |
|
76 | + $this->lookForBaseExpression($sql, $charPos, $parsed, 0, $backtracking); |
|
77 | + return $parsed; |
|
78 | + } |
|
79 | + |
|
80 | + private function findPositionWithinString($sql, $value, $expr_type) { |
|
81 | + |
|
82 | + $offset = 0; |
|
83 | + while (true) { |
|
84 | + |
|
85 | + $pos = strpos($sql, $value, $offset); |
|
86 | + if ($pos === false) { |
|
87 | + break; |
|
88 | + } |
|
89 | + |
|
90 | + $before = ""; |
|
91 | + if ($pos > 0) { |
|
92 | + $before = $sql[$pos - 1]; |
|
93 | + } |
|
94 | + |
|
95 | + $after = ""; |
|
96 | + if (isset($sql[$pos + strlen($value)])) { |
|
97 | + $after = $sql[$pos + strlen($value)]; |
|
98 | + } |
|
99 | + |
|
100 | + // if we have an operator, it should be surrounded by |
|
101 | + // whitespace, comma, parenthesis, digit or letter, end_of_string |
|
102 | + // an operator should not be surrounded by another operator |
|
103 | + |
|
104 | + if ($expr_type === 'operator') { |
|
105 | + |
|
106 | + $ok = ($before === "" || in_array($before, self::$allowedOnOperator, true)) |
|
107 | + || (strtolower($before) >= 'a' && strtolower($before) <= 'z') |
|
108 | + || ($before >= '0' && $before <= '9'); |
|
109 | + $ok = $ok |
|
110 | + && ($after === "" || in_array($after, self::$allowedOnOperator, true) |
|
111 | + || (strtolower($after) >= 'a' && strtolower($after) <= 'z') |
|
112 | + || ($after >= '0' && $after <= '9') || ($after === '?') || ($after === '@')); |
|
113 | + |
|
114 | + if (!$ok) { |
|
115 | + $offset = $pos + 1; |
|
116 | + continue; |
|
117 | + } |
|
118 | + |
|
119 | + break; |
|
120 | + } |
|
121 | + |
|
122 | + // in all other cases we accept |
|
123 | + // whitespace, comma, operators, parenthesis and end_of_string |
|
124 | + |
|
125 | + $ok = ($before === "" || in_array($before, self::$allowedOnOther, true)); |
|
126 | + $ok = $ok && ($after === "" || in_array($after, self::$allowedOnOther, true)); |
|
127 | + |
|
128 | + if ($ok) { |
|
129 | + break; |
|
130 | + } |
|
131 | + |
|
132 | + $offset = $pos + 1; |
|
133 | + } |
|
134 | + |
|
135 | + return $pos; |
|
136 | + } |
|
137 | + |
|
138 | + private function lookForBaseExpression($sql, &$charPos, &$parsed, $key, &$backtracking) { |
|
139 | + if (!is_numeric($key)) { |
|
140 | + if (($key === 'UNION' || $key === 'UNION ALL') || ($key === 'expr_type' && $parsed === 'expression') |
|
141 | + || ($key === 'expr_type' && $parsed === 'subquery') |
|
142 | + || ($key === 'expr_type' && $parsed === 'bracket_expression') |
|
143 | + || ($key === 'expr_type' && $parsed === 'table_expression') |
|
144 | + || ($key === 'expr_type' && $parsed === 'record') |
|
145 | + || ($key === 'expr_type' && $parsed === 'in-list') || ($key === 'alias' && $parsed !== false)) { |
|
146 | + // we hold the current position and come back after the next base_expr |
|
147 | + // we do this, because the next base_expr contains the complete expression/subquery/record |
|
148 | + // and we have to look into it too |
|
149 | + $backtracking[] = $charPos; |
|
150 | + |
|
151 | + } elseif (($key === 'ref_clause' || $key === 'columns') && $parsed !== false) { |
|
152 | + // we hold the current position and come back after n base_expr(s) |
|
153 | + // there is an array of sub-elements before (!) the base_expr clause of the current element |
|
154 | + // so we go through the sub-elements and must come at the end |
|
155 | + $backtracking[] = $charPos; |
|
156 | + $parsedCount = count($parsed); |
|
157 | + for ($i = 1; $i < $parsedCount; $i++) { |
|
158 | + $backtracking[] = false; // backtracking only after n base_expr! |
|
159 | + } |
|
160 | + } elseif ($key === 'sub_tree' && $parsed !== false) { |
|
161 | + // we prevent wrong backtracking on subtrees (too much array_pop()) |
|
162 | + // there is an array of sub-elements after(!) the base_expr clause of the current element |
|
163 | + // so we go through the sub-elements and must not come back at the end |
|
164 | + $parsedCount = count($parsed); |
|
165 | + for ($i = 1; $i < $parsedCount; $i++) { |
|
166 | + $backtracking[] = false; |
|
167 | + } |
|
168 | + } else { |
|
169 | + // move the current pos after the keyword |
|
170 | + // SELECT, WHERE, INSERT etc. |
|
171 | + if (in_array($key, parent::$reserved)) { |
|
172 | + $charPos = stripos($sql, $key, $charPos); |
|
173 | + $charPos += strlen($key); |
|
174 | + } |
|
175 | + } |
|
176 | + } |
|
177 | + |
|
178 | + if (!is_array($parsed)) { |
|
179 | + return; |
|
180 | + } |
|
181 | + |
|
182 | + foreach ($parsed as $key => $value) { |
|
183 | + if ($key === 'base_expr') { |
|
184 | + |
|
185 | + // $this->printPos("0", $sql, $charPos, $key, $value, $backtracking); |
|
186 | + |
|
187 | + $subject = substr($sql, $charPos); |
|
188 | + $pos = $this->findPositionWithinString($subject, $value, |
|
189 | + isset($parsed['expr_type']) ? $parsed['expr_type'] : 'alias'); |
|
190 | + if ($pos === false) { |
|
191 | + throw new Exception("cannot calculate position of " . $value . " within " . $subject, 5); |
|
192 | + |
|
193 | + } |
|
194 | + |
|
195 | + $parsed['position'] = $charPos + $pos; |
|
196 | + $charPos += $pos + strlen($value); |
|
197 | + |
|
198 | + // $this->printPos("1", $sql, $charPos, $key, $value, $backtracking); |
|
199 | + |
|
200 | + $oldPos = array_pop($backtracking); |
|
201 | + if (isset($oldPos) && $oldPos !== false) { |
|
202 | + $charPos = $oldPos; |
|
203 | + } |
|
204 | + |
|
205 | + // $this->printPos("2", $sql, $charPos, $key, $value, $backtracking); |
|
206 | + |
|
207 | + } else { |
|
208 | + $this->lookForBaseExpression($sql, $charPos, $parsed[$key], $key, $backtracking); |
|
209 | + } |
|
210 | + } |
|
211 | + } |
|
212 | 212 | } |
@@ -47,322 +47,322 @@ |
||
47 | 47 | */ |
48 | 48 | class RDatabaseSqlparserSqllexer extends RDatabaseSqlparserSqlparserutils { |
49 | 49 | |
50 | - private $splitters; |
|
50 | + private $splitters; |
|
51 | 51 | |
52 | - public function __construct() { |
|
53 | - $this->splitters = new RDatabaseSqlparserLexersplitter(); |
|
54 | - } |
|
52 | + public function __construct() { |
|
53 | + $this->splitters = new RDatabaseSqlparserLexersplitter(); |
|
54 | + } |
|
55 | 55 | |
56 | - public function split($sql) { |
|
57 | - if (!is_string($sql)) |
|
58 | - throw new InvalidArgumentException("no SQL string to parse: \n" . $sql, 10); |
|
56 | + public function split($sql) { |
|
57 | + if (!is_string($sql)) |
|
58 | + throw new InvalidArgumentException("no SQL string to parse: \n" . $sql, 10); |
|
59 | 59 | |
60 | - $tokens = array(); |
|
61 | - $token = ''; |
|
62 | - |
|
63 | - $splitLen = $this->splitters->getMaxLengthOfSplitter(); |
|
64 | - $len = strlen($sql); |
|
65 | - $pos = 0; |
|
66 | - |
|
67 | - while ($pos < $len) { |
|
68 | - |
|
69 | - for ($i = $splitLen; $i > 0; $i--) { |
|
70 | - $substr = substr($sql, $pos, $i); |
|
71 | - if ($this->splitters->isSplitter($substr)) { |
|
72 | - |
|
73 | - if ($token !== "") { |
|
74 | - $tokens[] = $token; |
|
75 | - } |
|
60 | + $tokens = array(); |
|
61 | + $token = ''; |
|
62 | + |
|
63 | + $splitLen = $this->splitters->getMaxLengthOfSplitter(); |
|
64 | + $len = strlen($sql); |
|
65 | + $pos = 0; |
|
66 | + |
|
67 | + while ($pos < $len) { |
|
68 | + |
|
69 | + for ($i = $splitLen; $i > 0; $i--) { |
|
70 | + $substr = substr($sql, $pos, $i); |
|
71 | + if ($this->splitters->isSplitter($substr)) { |
|
72 | + |
|
73 | + if ($token !== "") { |
|
74 | + $tokens[] = $token; |
|
75 | + } |
|
76 | 76 | |
77 | - $tokens[] = $substr; |
|
78 | - $pos += $i; |
|
79 | - $token = ''; |
|
77 | + $tokens[] = $substr; |
|
78 | + $pos += $i; |
|
79 | + $token = ''; |
|
80 | 80 | |
81 | - continue 2; |
|
82 | - } |
|
83 | - } |
|
81 | + continue 2; |
|
82 | + } |
|
83 | + } |
|
84 | 84 | |
85 | - $token .= $sql[$pos]; |
|
86 | - $pos++; |
|
87 | - } |
|
85 | + $token .= $sql[$pos]; |
|
86 | + $pos++; |
|
87 | + } |
|
88 | 88 | |
89 | - if ($token !== "") { |
|
90 | - $tokens[] = $token; |
|
91 | - } |
|
89 | + if ($token !== "") { |
|
90 | + $tokens[] = $token; |
|
91 | + } |
|
92 | 92 | |
93 | - $tokens = $this->concatEscapeSequences($tokens); |
|
94 | - $tokens = $this->balanceBackticks($tokens); |
|
95 | - $tokens = $this->concatColReferences($tokens); |
|
96 | - $tokens = $this->balanceParenthesis($tokens); |
|
97 | - $tokens = $this->balanceMultilineComments($tokens); |
|
98 | - $tokens = $this->concatInlineComments($tokens); |
|
99 | - $tokens = $this->concatUserDefinedVariables($tokens); |
|
100 | - return $tokens; |
|
101 | - } |
|
102 | - |
|
103 | - private function concatUserDefinedVariables($tokens) { |
|
104 | - $i = 0; |
|
105 | - $cnt = count($tokens); |
|
106 | - $userdef = false; |
|
107 | - |
|
108 | - while ($i < $cnt) { |
|
109 | - |
|
110 | - if (!isset($tokens[$i])) { |
|
111 | - $i++; |
|
112 | - continue; |
|
113 | - } |
|
114 | - |
|
115 | - $token = $tokens[$i]; |
|
116 | - |
|
117 | - if ($userdef !== false) { |
|
118 | - $tokens[$userdef] .= $token; |
|
119 | - unset($tokens[$i]); |
|
120 | - if ($token !== "@") { |
|
121 | - $userdef = false; |
|
122 | - } |
|
123 | - } |
|
124 | - |
|
125 | - if ($userdef === false && $token === "@") { |
|
126 | - $userdef = $i; |
|
127 | - } |
|
128 | - |
|
129 | - $i++; |
|
130 | - } |
|
131 | - |
|
132 | - return array_values($tokens); |
|
133 | - } |
|
134 | - |
|
135 | - private function concatInlineComments($tokens) { |
|
136 | - |
|
137 | - $i = 0; |
|
138 | - $cnt = count($tokens); |
|
139 | - $comment = false; |
|
140 | - |
|
141 | - while ($i < $cnt) { |
|
142 | - |
|
143 | - if (!isset($tokens[$i])) { |
|
144 | - $i++; |
|
145 | - continue; |
|
146 | - } |
|
147 | - |
|
148 | - $token = $tokens[$i]; |
|
149 | - |
|
150 | - if ($comment !== false) { |
|
151 | - if ($token === "\n" || $token === "\r\n") { |
|
152 | - $comment = false; |
|
153 | - } else { |
|
154 | - unset($tokens[$i]); |
|
155 | - $tokens[$comment] .= $token; |
|
156 | - } |
|
157 | - } |
|
158 | - |
|
159 | - if (($comment === false) && ($token === "-")) { |
|
160 | - if (isset($tokens[$i + 1]) && $tokens[$i + 1] === "-") { |
|
161 | - $comment = $i; |
|
162 | - $tokens[$i] = "--"; |
|
163 | - $i++; |
|
164 | - unset($tokens[$i]); |
|
165 | - continue; |
|
166 | - } |
|
167 | - } |
|
168 | - |
|
169 | - $i++; |
|
170 | - } |
|
171 | - |
|
172 | - return array_values($tokens); |
|
173 | - } |
|
174 | - |
|
175 | - private function balanceMultilineComments($tokens) { |
|
176 | - |
|
177 | - $i = 0; |
|
178 | - $cnt = count($tokens); |
|
179 | - $comment = false; |
|
180 | - |
|
181 | - while ($i < $cnt) { |
|
182 | - |
|
183 | - if (!isset($tokens[$i])) { |
|
184 | - $i++; |
|
185 | - continue; |
|
186 | - } |
|
187 | - |
|
188 | - $token = $tokens[$i]; |
|
189 | - |
|
190 | - if ($comment !== false) { |
|
191 | - unset($tokens[$i]); |
|
192 | - $tokens[$comment] .= $token; |
|
193 | - if ($token === "*" && isset($tokens[$i + 1]) && $tokens[$i + 1] === "/") { |
|
194 | - unset($tokens[$i + 1]); |
|
195 | - $tokens[$comment] .= "/"; |
|
196 | - $comment = false; |
|
197 | - } |
|
198 | - } |
|
199 | - |
|
200 | - if (($comment === false) && ($token === "/")) { |
|
201 | - if (isset($tokens[$i + 1]) && $tokens[$i + 1] === "*") { |
|
202 | - $comment = $i; |
|
203 | - $tokens[$i] = "/*"; |
|
204 | - $i++; |
|
205 | - unset($tokens[$i]); |
|
206 | - continue; |
|
207 | - } |
|
208 | - } |
|
209 | - |
|
210 | - $i++; |
|
211 | - } |
|
212 | - return array_values($tokens); |
|
213 | - } |
|
214 | - |
|
215 | - private function isBacktick($token) { |
|
216 | - return ($token === "'" || $token === "\"" || $token === "`"); |
|
217 | - } |
|
218 | - |
|
219 | - private function balanceBackticks($tokens) { |
|
220 | - $i = 0; |
|
221 | - $cnt = count($tokens); |
|
222 | - while ($i < $cnt) { |
|
223 | - |
|
224 | - if (!isset($tokens[$i])) { |
|
225 | - $i++; |
|
226 | - continue; |
|
227 | - } |
|
228 | - |
|
229 | - $token = $tokens[$i]; |
|
230 | - |
|
231 | - if ($this->isBacktick($token)) { |
|
232 | - $tokens = $this->balanceCharacter($tokens, $i, $token); |
|
233 | - } |
|
234 | - |
|
235 | - $i++; |
|
236 | - } |
|
237 | - |
|
238 | - return $tokens; |
|
239 | - } |
|
93 | + $tokens = $this->concatEscapeSequences($tokens); |
|
94 | + $tokens = $this->balanceBackticks($tokens); |
|
95 | + $tokens = $this->concatColReferences($tokens); |
|
96 | + $tokens = $this->balanceParenthesis($tokens); |
|
97 | + $tokens = $this->balanceMultilineComments($tokens); |
|
98 | + $tokens = $this->concatInlineComments($tokens); |
|
99 | + $tokens = $this->concatUserDefinedVariables($tokens); |
|
100 | + return $tokens; |
|
101 | + } |
|
102 | + |
|
103 | + private function concatUserDefinedVariables($tokens) { |
|
104 | + $i = 0; |
|
105 | + $cnt = count($tokens); |
|
106 | + $userdef = false; |
|
107 | + |
|
108 | + while ($i < $cnt) { |
|
109 | + |
|
110 | + if (!isset($tokens[$i])) { |
|
111 | + $i++; |
|
112 | + continue; |
|
113 | + } |
|
114 | + |
|
115 | + $token = $tokens[$i]; |
|
116 | + |
|
117 | + if ($userdef !== false) { |
|
118 | + $tokens[$userdef] .= $token; |
|
119 | + unset($tokens[$i]); |
|
120 | + if ($token !== "@") { |
|
121 | + $userdef = false; |
|
122 | + } |
|
123 | + } |
|
124 | + |
|
125 | + if ($userdef === false && $token === "@") { |
|
126 | + $userdef = $i; |
|
127 | + } |
|
128 | + |
|
129 | + $i++; |
|
130 | + } |
|
131 | + |
|
132 | + return array_values($tokens); |
|
133 | + } |
|
134 | + |
|
135 | + private function concatInlineComments($tokens) { |
|
136 | + |
|
137 | + $i = 0; |
|
138 | + $cnt = count($tokens); |
|
139 | + $comment = false; |
|
140 | + |
|
141 | + while ($i < $cnt) { |
|
142 | + |
|
143 | + if (!isset($tokens[$i])) { |
|
144 | + $i++; |
|
145 | + continue; |
|
146 | + } |
|
147 | + |
|
148 | + $token = $tokens[$i]; |
|
149 | + |
|
150 | + if ($comment !== false) { |
|
151 | + if ($token === "\n" || $token === "\r\n") { |
|
152 | + $comment = false; |
|
153 | + } else { |
|
154 | + unset($tokens[$i]); |
|
155 | + $tokens[$comment] .= $token; |
|
156 | + } |
|
157 | + } |
|
158 | + |
|
159 | + if (($comment === false) && ($token === "-")) { |
|
160 | + if (isset($tokens[$i + 1]) && $tokens[$i + 1] === "-") { |
|
161 | + $comment = $i; |
|
162 | + $tokens[$i] = "--"; |
|
163 | + $i++; |
|
164 | + unset($tokens[$i]); |
|
165 | + continue; |
|
166 | + } |
|
167 | + } |
|
168 | + |
|
169 | + $i++; |
|
170 | + } |
|
171 | + |
|
172 | + return array_values($tokens); |
|
173 | + } |
|
174 | + |
|
175 | + private function balanceMultilineComments($tokens) { |
|
176 | + |
|
177 | + $i = 0; |
|
178 | + $cnt = count($tokens); |
|
179 | + $comment = false; |
|
180 | + |
|
181 | + while ($i < $cnt) { |
|
182 | + |
|
183 | + if (!isset($tokens[$i])) { |
|
184 | + $i++; |
|
185 | + continue; |
|
186 | + } |
|
187 | + |
|
188 | + $token = $tokens[$i]; |
|
189 | + |
|
190 | + if ($comment !== false) { |
|
191 | + unset($tokens[$i]); |
|
192 | + $tokens[$comment] .= $token; |
|
193 | + if ($token === "*" && isset($tokens[$i + 1]) && $tokens[$i + 1] === "/") { |
|
194 | + unset($tokens[$i + 1]); |
|
195 | + $tokens[$comment] .= "/"; |
|
196 | + $comment = false; |
|
197 | + } |
|
198 | + } |
|
199 | + |
|
200 | + if (($comment === false) && ($token === "/")) { |
|
201 | + if (isset($tokens[$i + 1]) && $tokens[$i + 1] === "*") { |
|
202 | + $comment = $i; |
|
203 | + $tokens[$i] = "/*"; |
|
204 | + $i++; |
|
205 | + unset($tokens[$i]); |
|
206 | + continue; |
|
207 | + } |
|
208 | + } |
|
209 | + |
|
210 | + $i++; |
|
211 | + } |
|
212 | + return array_values($tokens); |
|
213 | + } |
|
214 | + |
|
215 | + private function isBacktick($token) { |
|
216 | + return ($token === "'" || $token === "\"" || $token === "`"); |
|
217 | + } |
|
218 | + |
|
219 | + private function balanceBackticks($tokens) { |
|
220 | + $i = 0; |
|
221 | + $cnt = count($tokens); |
|
222 | + while ($i < $cnt) { |
|
223 | + |
|
224 | + if (!isset($tokens[$i])) { |
|
225 | + $i++; |
|
226 | + continue; |
|
227 | + } |
|
228 | + |
|
229 | + $token = $tokens[$i]; |
|
230 | + |
|
231 | + if ($this->isBacktick($token)) { |
|
232 | + $tokens = $this->balanceCharacter($tokens, $i, $token); |
|
233 | + } |
|
234 | + |
|
235 | + $i++; |
|
236 | + } |
|
237 | + |
|
238 | + return $tokens; |
|
239 | + } |
|
240 | 240 | |
241 | 241 | // backticks are not balanced within one token, so we have |
242 | 242 | // to re-combine some tokens |
243 | - private function balanceCharacter($tokens, $idx, $char) { |
|
243 | + private function balanceCharacter($tokens, $idx, $char) { |
|
244 | 244 | |
245 | - $token_count = count($tokens); |
|
246 | - $i = $idx + 1; |
|
247 | - while ($i < $token_count) { |
|
245 | + $token_count = count($tokens); |
|
246 | + $i = $idx + 1; |
|
247 | + while ($i < $token_count) { |
|
248 | 248 | |
249 | - if (!isset($tokens[$i])) { |
|
250 | - $i++; |
|
251 | - continue; |
|
252 | - } |
|
249 | + if (!isset($tokens[$i])) { |
|
250 | + $i++; |
|
251 | + continue; |
|
252 | + } |
|
253 | 253 | |
254 | - $token = $tokens[$i]; |
|
255 | - $tokens[$idx] .= $token; |
|
256 | - unset($tokens[$i]); |
|
254 | + $token = $tokens[$i]; |
|
255 | + $tokens[$idx] .= $token; |
|
256 | + unset($tokens[$i]); |
|
257 | 257 | |
258 | - if ($token === $char) { |
|
259 | - break; |
|
260 | - } |
|
258 | + if ($token === $char) { |
|
259 | + break; |
|
260 | + } |
|
261 | 261 | |
262 | - $i++; |
|
263 | - } |
|
264 | - return array_values($tokens); |
|
265 | - } |
|
262 | + $i++; |
|
263 | + } |
|
264 | + return array_values($tokens); |
|
265 | + } |
|
266 | 266 | |
267 | - /* |
|
267 | + /* |
|
268 | 268 | * does the token ends with dot? |
269 | 269 | * concat it with the next token |
270 | 270 | * |
271 | 271 | * does the token starts with a dot? |
272 | 272 | * concat it with the previous token |
273 | 273 | */ |
274 | - private function concatColReferences($tokens) { |
|
275 | - |
|
276 | - $cnt = count($tokens); |
|
277 | - $i = 0; |
|
278 | - while ($i < $cnt) { |
|
279 | - |
|
280 | - if (!isset($tokens[$i])) { |
|
281 | - $i++; |
|
282 | - continue; |
|
283 | - } |
|
284 | - |
|
285 | - if ($tokens[$i][0] === ".") { |
|
286 | - |
|
287 | - // concat the previous tokens, till the token has been changed |
|
288 | - $k = $i - 1; |
|
289 | - $len = strlen($tokens[$i]); |
|
290 | - while (($k >= 0) && ($len == strlen($tokens[$i]))) { |
|
291 | - if (!isset($tokens[$k])) { // FIXME: this can be wrong if we have schema . table . column |
|
292 | - $k--; |
|
293 | - continue; |
|
294 | - } |
|
295 | - $tokens[$i] = $tokens[$k] . $tokens[$i]; |
|
296 | - unset($tokens[$k]); |
|
297 | - $k--; |
|
298 | - } |
|
299 | - } |
|
300 | - |
|
301 | - if ($this->endsWith($tokens[$i], '.')) { |
|
302 | - |
|
303 | - // concat the next tokens, till the token has been changed |
|
304 | - $k = $i + 1; |
|
305 | - $len = strlen($tokens[$i]); |
|
306 | - while (($k < $cnt) && ($len == strlen($tokens[$i]))) { |
|
307 | - if (!isset($tokens[$k])) { |
|
308 | - $k++; |
|
309 | - continue; |
|
310 | - } |
|
311 | - $tokens[$i] .= $tokens[$k]; |
|
312 | - unset($tokens[$k]); |
|
313 | - $k++; |
|
314 | - } |
|
315 | - } |
|
316 | - |
|
317 | - $i++; |
|
318 | - } |
|
319 | - |
|
320 | - return array_values($tokens); |
|
321 | - } |
|
322 | - |
|
323 | - private function concatEscapeSequences($tokens) { |
|
324 | - $tokenCount = count($tokens); |
|
325 | - $i = 0; |
|
326 | - while ($i < $tokenCount) { |
|
327 | - |
|
328 | - if ($this->endsWith($tokens[$i], "\\")) { |
|
329 | - $i++; |
|
330 | - if (isset($tokens[$i])) { |
|
331 | - $tokens[$i - 1] .= $tokens[$i]; |
|
332 | - unset($tokens[$i]); |
|
333 | - } |
|
334 | - } |
|
335 | - $i++; |
|
336 | - } |
|
337 | - return array_values($tokens); |
|
338 | - } |
|
339 | - |
|
340 | - private function balanceParenthesis($tokens) { |
|
341 | - $token_count = count($tokens); |
|
342 | - $i = 0; |
|
343 | - while ($i < $token_count) { |
|
344 | - if ($tokens[$i] !== '(') { |
|
345 | - $i++; |
|
346 | - continue; |
|
347 | - } |
|
348 | - $count = 1; |
|
349 | - for ($n = $i + 1; $n < $token_count; $n++) { |
|
350 | - $token = $tokens[$n]; |
|
351 | - if ($token === '(') { |
|
352 | - $count++; |
|
353 | - } |
|
354 | - if ($token === ')') { |
|
355 | - $count--; |
|
356 | - } |
|
357 | - $tokens[$i] .= $token; |
|
358 | - unset($tokens[$n]); |
|
359 | - if ($count === 0) { |
|
360 | - $n++; |
|
361 | - break; |
|
362 | - } |
|
363 | - } |
|
364 | - $i = $n; |
|
365 | - } |
|
366 | - return array_values($tokens); |
|
367 | - } |
|
274 | + private function concatColReferences($tokens) { |
|
275 | + |
|
276 | + $cnt = count($tokens); |
|
277 | + $i = 0; |
|
278 | + while ($i < $cnt) { |
|
279 | + |
|
280 | + if (!isset($tokens[$i])) { |
|
281 | + $i++; |
|
282 | + continue; |
|
283 | + } |
|
284 | + |
|
285 | + if ($tokens[$i][0] === ".") { |
|
286 | + |
|
287 | + // concat the previous tokens, till the token has been changed |
|
288 | + $k = $i - 1; |
|
289 | + $len = strlen($tokens[$i]); |
|
290 | + while (($k >= 0) && ($len == strlen($tokens[$i]))) { |
|
291 | + if (!isset($tokens[$k])) { // FIXME: this can be wrong if we have schema . table . column |
|
292 | + $k--; |
|
293 | + continue; |
|
294 | + } |
|
295 | + $tokens[$i] = $tokens[$k] . $tokens[$i]; |
|
296 | + unset($tokens[$k]); |
|
297 | + $k--; |
|
298 | + } |
|
299 | + } |
|
300 | + |
|
301 | + if ($this->endsWith($tokens[$i], '.')) { |
|
302 | + |
|
303 | + // concat the next tokens, till the token has been changed |
|
304 | + $k = $i + 1; |
|
305 | + $len = strlen($tokens[$i]); |
|
306 | + while (($k < $cnt) && ($len == strlen($tokens[$i]))) { |
|
307 | + if (!isset($tokens[$k])) { |
|
308 | + $k++; |
|
309 | + continue; |
|
310 | + } |
|
311 | + $tokens[$i] .= $tokens[$k]; |
|
312 | + unset($tokens[$k]); |
|
313 | + $k++; |
|
314 | + } |
|
315 | + } |
|
316 | + |
|
317 | + $i++; |
|
318 | + } |
|
319 | + |
|
320 | + return array_values($tokens); |
|
321 | + } |
|
322 | + |
|
323 | + private function concatEscapeSequences($tokens) { |
|
324 | + $tokenCount = count($tokens); |
|
325 | + $i = 0; |
|
326 | + while ($i < $tokenCount) { |
|
327 | + |
|
328 | + if ($this->endsWith($tokens[$i], "\\")) { |
|
329 | + $i++; |
|
330 | + if (isset($tokens[$i])) { |
|
331 | + $tokens[$i - 1] .= $tokens[$i]; |
|
332 | + unset($tokens[$i]); |
|
333 | + } |
|
334 | + } |
|
335 | + $i++; |
|
336 | + } |
|
337 | + return array_values($tokens); |
|
338 | + } |
|
339 | + |
|
340 | + private function balanceParenthesis($tokens) { |
|
341 | + $token_count = count($tokens); |
|
342 | + $i = 0; |
|
343 | + while ($i < $token_count) { |
|
344 | + if ($tokens[$i] !== '(') { |
|
345 | + $i++; |
|
346 | + continue; |
|
347 | + } |
|
348 | + $count = 1; |
|
349 | + for ($n = $i + 1; $n < $token_count; $n++) { |
|
350 | + $token = $tokens[$n]; |
|
351 | + if ($token === '(') { |
|
352 | + $count++; |
|
353 | + } |
|
354 | + if ($token === ')') { |
|
355 | + $count--; |
|
356 | + } |
|
357 | + $tokens[$i] .= $token; |
|
358 | + unset($tokens[$n]); |
|
359 | + if ($count === 0) { |
|
360 | + $n++; |
|
361 | + break; |
|
362 | + } |
|
363 | + } |
|
364 | + $i = $n; |
|
365 | + } |
|
366 | + return array_values($tokens); |
|
367 | + } |
|
368 | 368 | } |
@@ -42,791 +42,791 @@ |
||
42 | 42 | * @see OAuth2\Controller\TokenController |
43 | 43 | */ |
44 | 44 | class Server implements ResourceControllerInterface, |
45 | - AuthorizeControllerInterface, |
|
46 | - TokenControllerInterface, |
|
47 | - UserInfoControllerInterface |
|
45 | + AuthorizeControllerInterface, |
|
46 | + TokenControllerInterface, |
|
47 | + UserInfoControllerInterface |
|
48 | 48 | { |
49 | - // misc properties |
|
50 | - protected $response; |
|
51 | - protected $config; |
|
52 | - protected $storages; |
|
53 | - |
|
54 | - // servers |
|
55 | - protected $authorizeController; |
|
56 | - protected $tokenController; |
|
57 | - protected $resourceController; |
|
58 | - protected $userInfoController; |
|
59 | - |
|
60 | - // config classes |
|
61 | - protected $grantTypes; |
|
62 | - protected $responseTypes; |
|
63 | - protected $tokenType; |
|
64 | - protected $scopeUtil; |
|
65 | - protected $clientAssertionType; |
|
66 | - |
|
67 | - protected $storageMap = array( |
|
68 | - 'access_token' => 'OAuth2\Storage\AccessTokenInterface', |
|
69 | - 'authorization_code' => 'OAuth2\Storage\AuthorizationCodeInterface', |
|
70 | - 'client_credentials' => 'OAuth2\Storage\ClientCredentialsInterface', |
|
71 | - 'client' => 'OAuth2\Storage\ClientInterface', |
|
72 | - 'refresh_token' => 'OAuth2\Storage\RefreshTokenInterface', |
|
73 | - 'user_credentials' => 'OAuth2\Storage\UserCredentialsInterface', |
|
74 | - 'user_claims' => 'OAuth2\OpenID\Storage\UserClaimsInterface', |
|
75 | - 'public_key' => 'OAuth2\Storage\PublicKeyInterface', |
|
76 | - 'jwt_bearer' => 'OAuth2\Storage\JWTBearerInterface', |
|
77 | - 'scope' => 'OAuth2\Storage\ScopeInterface', |
|
78 | - ); |
|
79 | - |
|
80 | - protected $responseTypeMap = array( |
|
81 | - 'token' => 'OAuth2\ResponseType\AccessTokenInterface', |
|
82 | - 'code' => 'OAuth2\ResponseType\AuthorizationCodeInterface', |
|
83 | - 'id_token' => 'OAuth2\OpenID\ResponseType\IdTokenInterface', |
|
84 | - 'id_token token' => 'OAuth2\OpenID\ResponseType\IdTokenTokenInterface', |
|
85 | - 'code id_token' => 'OAuth2\OpenID\ResponseType\CodeIdTokenInterface', |
|
86 | - ); |
|
87 | - |
|
88 | - /** |
|
89 | - * @param mixed $storage (array or OAuth2\Storage) - single object or array of objects implementing the |
|
90 | - * required storage types (ClientCredentialsInterface and AccessTokenInterface as a minimum) |
|
91 | - * @param array $config specify a different token lifetime, token header name, etc |
|
92 | - * @param array $grantTypes An array of OAuth2\GrantType\GrantTypeInterface to use for granting access tokens |
|
93 | - * @param array $responseTypes Response types to use. array keys should be "code" and and "token" for |
|
94 | - * Access Token and Authorization Code response types |
|
95 | - * @param OAuth2\TokenType\TokenTypeInterface $tokenType The token type object to use. Valid token types are "bearer" and "mac" |
|
96 | - * @param OAuth2\ScopeInterface $scopeUtil The scope utility class to use to validate scope |
|
97 | - * @param OAuth2\ClientAssertionType\ClientAssertionTypeInterface $clientAssertionType The method in which to verify the client identity. Default is HttpBasic |
|
98 | - * |
|
99 | - * @ingroup oauth2_section_7 |
|
100 | - */ |
|
101 | - public function __construct($storage = array(), array $config = array(), array $grantTypes = array(), array $responseTypes = array(), TokenTypeInterface $tokenType = null, ScopeInterface $scopeUtil = null, ClientAssertionTypeInterface $clientAssertionType = null) |
|
102 | - { |
|
103 | - $storage = is_array($storage) ? $storage : array($storage); |
|
104 | - $this->storages = array(); |
|
105 | - foreach ($storage as $key => $service) { |
|
106 | - $this->addStorage($service, $key); |
|
107 | - } |
|
108 | - |
|
109 | - // merge all config values. These get passed to our controller objects |
|
110 | - $this->config = array_merge(array( |
|
111 | - 'use_jwt_access_tokens' => false, |
|
112 | - 'store_encrypted_token_string' => true, |
|
113 | - 'use_openid_connect' => false, |
|
114 | - 'id_lifetime' => 3600, |
|
115 | - 'access_lifetime' => 3600, |
|
116 | - 'www_realm' => 'Service', |
|
117 | - 'token_param_name' => 'access_token', |
|
118 | - 'token_bearer_header_name' => 'Bearer', |
|
119 | - 'enforce_state' => true, |
|
120 | - 'require_exact_redirect_uri' => true, |
|
121 | - 'allow_implicit' => false, |
|
122 | - 'allow_credentials_in_request_body' => true, |
|
123 | - 'allow_public_clients' => true, |
|
124 | - 'always_issue_new_refresh_token' => false, |
|
125 | - 'unset_refresh_token_after_use' => true, |
|
126 | - ), $config); |
|
127 | - |
|
128 | - foreach ($grantTypes as $key => $grantType) { |
|
129 | - $this->addGrantType($grantType, $key); |
|
130 | - } |
|
131 | - |
|
132 | - foreach ($responseTypes as $key => $responseType) { |
|
133 | - $this->addResponseType($responseType, $key); |
|
134 | - } |
|
135 | - |
|
136 | - $this->tokenType = $tokenType; |
|
137 | - $this->scopeUtil = $scopeUtil; |
|
138 | - $this->clientAssertionType = $clientAssertionType; |
|
139 | - |
|
140 | - if ($this->config['use_openid_connect']) { |
|
141 | - $this->validateOpenIdConnect(); |
|
142 | - } |
|
143 | - } |
|
144 | - |
|
145 | - public function getAuthorizeController() |
|
146 | - { |
|
147 | - if (is_null($this->authorizeController)) { |
|
148 | - $this->authorizeController = $this->createDefaultAuthorizeController(); |
|
149 | - } |
|
150 | - |
|
151 | - return $this->authorizeController; |
|
152 | - } |
|
153 | - |
|
154 | - public function getTokenController() |
|
155 | - { |
|
156 | - if (is_null($this->tokenController)) { |
|
157 | - $this->tokenController = $this->createDefaultTokenController(); |
|
158 | - } |
|
159 | - |
|
160 | - return $this->tokenController; |
|
161 | - } |
|
162 | - |
|
163 | - public function getResourceController() |
|
164 | - { |
|
165 | - if (is_null($this->resourceController)) { |
|
166 | - $this->resourceController = $this->createDefaultResourceController(); |
|
167 | - } |
|
168 | - |
|
169 | - return $this->resourceController; |
|
170 | - } |
|
171 | - |
|
172 | - public function getUserInfoController() |
|
173 | - { |
|
174 | - if (is_null($this->userInfoController)) { |
|
175 | - $this->userInfoController = $this->createDefaultUserInfoController(); |
|
176 | - } |
|
177 | - |
|
178 | - return $this->userInfoController; |
|
179 | - } |
|
180 | - |
|
181 | - /** |
|
182 | - * every getter deserves a setter |
|
183 | - */ |
|
184 | - public function setAuthorizeController(AuthorizeControllerInterface $authorizeController) |
|
185 | - { |
|
186 | - $this->authorizeController = $authorizeController; |
|
187 | - } |
|
188 | - |
|
189 | - /** |
|
190 | - * every getter deserves a setter |
|
191 | - */ |
|
192 | - public function setTokenController(TokenControllerInterface $tokenController) |
|
193 | - { |
|
194 | - $this->tokenController = $tokenController; |
|
195 | - } |
|
196 | - |
|
197 | - /** |
|
198 | - * every getter deserves a setter |
|
199 | - */ |
|
200 | - public function setResourceController(ResourceControllerInterface $resourceController) |
|
201 | - { |
|
202 | - $this->resourceController = $resourceController; |
|
203 | - } |
|
204 | - |
|
205 | - /** |
|
206 | - * every getter deserves a setter |
|
207 | - */ |
|
208 | - public function setUserInfoController(UserInfoControllerInterface $userInfoController) |
|
209 | - { |
|
210 | - $this->userInfoController = $userInfoController; |
|
211 | - } |
|
212 | - |
|
213 | - /** |
|
214 | - * Return claims about the authenticated end-user. |
|
215 | - * This would be called from the "/UserInfo" endpoint as defined in the spec. |
|
216 | - * |
|
217 | - * @param $request - OAuth2\RequestInterface |
|
218 | - * Request object to grant access token |
|
219 | - * |
|
220 | - * @param $response - OAuth2\ResponseInterface |
|
221 | - * Response object containing error messages (failure) or user claims (success) |
|
222 | - * |
|
223 | - * @throws InvalidArgumentException |
|
224 | - * @throws LogicException |
|
225 | - * |
|
226 | - * @see http://openid.net/specs/openid-connect-core-1_0.html#UserInfo |
|
227 | - */ |
|
228 | - public function handleUserInfoRequest(RequestInterface $request, ResponseInterface $response = null) |
|
229 | - { |
|
230 | - $this->response = is_null($response) ? new Response() : $response; |
|
231 | - $this->getUserInfoController()->handleUserInfoRequest($request, $this->response); |
|
232 | - |
|
233 | - return $this->response; |
|
234 | - } |
|
235 | - |
|
236 | - /** |
|
237 | - * Grant or deny a requested access token. |
|
238 | - * This would be called from the "/token" endpoint as defined in the spec. |
|
239 | - * Obviously, you can call your endpoint whatever you want. |
|
240 | - * |
|
241 | - * @param $request - OAuth2\RequestInterface |
|
242 | - * Request object to grant access token |
|
243 | - * |
|
244 | - * @param $response - OAuth2\ResponseInterface |
|
245 | - * Response object containing error messages (failure) or access token (success) |
|
246 | - * |
|
247 | - * @throws InvalidArgumentException |
|
248 | - * @throws LogicException |
|
249 | - * |
|
250 | - * @see http://tools.ietf.org/html/rfc6749#section-4 |
|
251 | - * @see http://tools.ietf.org/html/rfc6749#section-10.6 |
|
252 | - * @see http://tools.ietf.org/html/rfc6749#section-4.1.3 |
|
253 | - * |
|
254 | - * @ingroup oauth2_section_4 |
|
255 | - */ |
|
256 | - public function handleTokenRequest(RequestInterface $request, ResponseInterface $response = null) |
|
257 | - { |
|
258 | - $this->response = is_null($response) ? new Response() : $response; |
|
259 | - $this->getTokenController()->handleTokenRequest($request, $this->response); |
|
260 | - |
|
261 | - return $this->response; |
|
262 | - } |
|
263 | - |
|
264 | - public function grantAccessToken(RequestInterface $request, ResponseInterface $response = null) |
|
265 | - { |
|
266 | - $this->response = is_null($response) ? new Response() : $response; |
|
267 | - $value = $this->getTokenController()->grantAccessToken($request, $this->response); |
|
268 | - |
|
269 | - return $value; |
|
270 | - } |
|
271 | - |
|
272 | - /** |
|
273 | - * Handle a revoke token request |
|
274 | - * This would be called from the "/revoke" endpoint as defined in the draft Token Revocation spec |
|
275 | - * |
|
276 | - * @see https://tools.ietf.org/html/rfc7009#section-2 |
|
277 | - * |
|
278 | - * @param RequestInterface $request |
|
279 | - * @param ResponseInterface $response |
|
280 | - * @return Response|ResponseInterface |
|
281 | - */ |
|
282 | - public function handleRevokeRequest(RequestInterface $request, ResponseInterface $response = null) |
|
283 | - { |
|
284 | - $this->response = is_null($response) ? new Response() : $response; |
|
285 | - $this->getTokenController()->handleRevokeRequest($request, $this->response); |
|
286 | - |
|
287 | - return $this->response; |
|
288 | - } |
|
289 | - |
|
290 | - /** |
|
291 | - * Redirect the user appropriately after approval. |
|
292 | - * |
|
293 | - * After the user has approved or denied the resource request the |
|
294 | - * authorization server should call this function to redirect the user |
|
295 | - * appropriately. |
|
296 | - * |
|
297 | - * @param $request |
|
298 | - * The request should have the follow parameters set in the querystring: |
|
299 | - * - response_type: The requested response: an access token, an |
|
300 | - * authorization code, or both. |
|
301 | - * - client_id: The client identifier as described in Section 2. |
|
302 | - * - redirect_uri: An absolute URI to which the authorization server |
|
303 | - * will redirect the user-agent to when the end-user authorization |
|
304 | - * step is completed. |
|
305 | - * - scope: (optional) The scope of the resource request expressed as a |
|
306 | - * list of space-delimited strings. |
|
307 | - * - state: (optional) An opaque value used by the client to maintain |
|
308 | - * state between the request and callback. |
|
309 | - * @param $is_authorized |
|
310 | - * TRUE or FALSE depending on whether the user authorized the access. |
|
311 | - * @param $user_id |
|
312 | - * Identifier of user who authorized the client |
|
313 | - * |
|
314 | - * @see http://tools.ietf.org/html/rfc6749#section-4 |
|
315 | - * |
|
316 | - * @ingroup oauth2_section_4 |
|
317 | - */ |
|
318 | - public function handleAuthorizeRequest(RequestInterface $request, ResponseInterface $response, $is_authorized, $user_id = null) |
|
319 | - { |
|
320 | - $this->response = $response; |
|
321 | - $this->getAuthorizeController()->handleAuthorizeRequest($request, $this->response, $is_authorized, $user_id); |
|
322 | - |
|
323 | - return $this->response; |
|
324 | - } |
|
325 | - |
|
326 | - /** |
|
327 | - * Pull the authorization request data out of the HTTP request. |
|
328 | - * - The redirect_uri is OPTIONAL as per draft 20. But your implementation can enforce it |
|
329 | - * by setting $config['enforce_redirect'] to true. |
|
330 | - * - The state is OPTIONAL but recommended to enforce CSRF. Draft 21 states, however, that |
|
331 | - * CSRF protection is MANDATORY. You can enforce this by setting the $config['enforce_state'] to true. |
|
332 | - * |
|
333 | - * The draft specifies that the parameters should be retrieved from GET, override the Response |
|
334 | - * object to change this |
|
335 | - * |
|
336 | - * @return |
|
337 | - * The authorization parameters so the authorization server can prompt |
|
338 | - * the user for approval if valid. |
|
339 | - * |
|
340 | - * @see http://tools.ietf.org/html/rfc6749#section-4.1.1 |
|
341 | - * @see http://tools.ietf.org/html/rfc6749#section-10.12 |
|
342 | - * |
|
343 | - * @ingroup oauth2_section_3 |
|
344 | - */ |
|
345 | - public function validateAuthorizeRequest(RequestInterface $request, ResponseInterface $response = null) |
|
346 | - { |
|
347 | - $this->response = is_null($response) ? new Response() : $response; |
|
348 | - $value = $this->getAuthorizeController()->validateAuthorizeRequest($request, $this->response); |
|
349 | - |
|
350 | - return $value; |
|
351 | - } |
|
352 | - |
|
353 | - public function verifyResourceRequest(RequestInterface $request, ResponseInterface $response = null, $scope = null) |
|
354 | - { |
|
355 | - $this->response = is_null($response) ? new Response() : $response; |
|
356 | - $value = $this->getResourceController()->verifyResourceRequest($request, $this->response, $scope); |
|
357 | - |
|
358 | - return $value; |
|
359 | - } |
|
360 | - |
|
361 | - public function getAccessTokenData(RequestInterface $request, ResponseInterface $response = null) |
|
362 | - { |
|
363 | - $this->response = is_null($response) ? new Response() : $response; |
|
364 | - $value = $this->getResourceController()->getAccessTokenData($request, $this->response); |
|
365 | - |
|
366 | - return $value; |
|
367 | - } |
|
368 | - |
|
369 | - public function addGrantType(GrantTypeInterface $grantType, $identifier = null) |
|
370 | - { |
|
371 | - if (!is_string($identifier)) { |
|
372 | - $identifier = $grantType->getQuerystringIdentifier(); |
|
373 | - } |
|
374 | - |
|
375 | - $this->grantTypes[$identifier] = $grantType; |
|
376 | - |
|
377 | - // persist added grant type down to TokenController |
|
378 | - if (!is_null($this->tokenController)) { |
|
379 | - $this->getTokenController()->addGrantType($grantType, $identifier); |
|
380 | - } |
|
381 | - } |
|
382 | - |
|
383 | - /** |
|
384 | - * Set a storage object for the server |
|
385 | - * |
|
386 | - * @param $storage |
|
387 | - * An object implementing one of the Storage interfaces |
|
388 | - * @param $key |
|
389 | - * If null, the storage is set to the key of each storage interface it implements |
|
390 | - * |
|
391 | - * @see storageMap |
|
392 | - */ |
|
393 | - public function addStorage($storage, $key = null) |
|
394 | - { |
|
395 | - // if explicitly set to a valid key, do not "magically" set below |
|
396 | - if (isset($this->storageMap[$key])) { |
|
397 | - if (!is_null($storage) && !$storage instanceof $this->storageMap[$key]) { |
|
398 | - throw new \InvalidArgumentException(sprintf('storage of type "%s" must implement interface "%s"', $key, $this->storageMap[$key])); |
|
399 | - } |
|
400 | - $this->storages[$key] = $storage; |
|
401 | - |
|
402 | - // special logic to handle "client" and "client_credentials" strangeness |
|
403 | - if ($key === 'client' && !isset($this->storages['client_credentials'])) { |
|
404 | - if ($storage instanceof \OAuth2\Storage\ClientCredentialsInterface) { |
|
405 | - $this->storages['client_credentials'] = $storage; |
|
406 | - } |
|
407 | - } elseif ($key === 'client_credentials' && !isset($this->storages['client'])) { |
|
408 | - if ($storage instanceof \OAuth2\Storage\ClientInterface) { |
|
409 | - $this->storages['client'] = $storage; |
|
410 | - } |
|
411 | - } |
|
412 | - } elseif (!is_null($key) && !is_numeric($key)) { |
|
413 | - throw new \InvalidArgumentException(sprintf('unknown storage key "%s", must be one of [%s]', $key, implode(', ', array_keys($this->storageMap)))); |
|
414 | - } else { |
|
415 | - $set = false; |
|
416 | - foreach ($this->storageMap as $type => $interface) { |
|
417 | - if ($storage instanceof $interface) { |
|
418 | - $this->storages[$type] = $storage; |
|
419 | - $set = true; |
|
420 | - } |
|
421 | - } |
|
422 | - |
|
423 | - if (!$set) { |
|
424 | - throw new \InvalidArgumentException(sprintf('storage of class "%s" must implement one of [%s]', get_class($storage), implode(', ', $this->storageMap))); |
|
425 | - } |
|
426 | - } |
|
427 | - } |
|
428 | - |
|
429 | - public function addResponseType(ResponseTypeInterface $responseType, $key = null) |
|
430 | - { |
|
431 | - $key = $this->normalizeResponseType($key); |
|
432 | - |
|
433 | - if (isset($this->responseTypeMap[$key])) { |
|
434 | - if (!$responseType instanceof $this->responseTypeMap[$key]) { |
|
435 | - throw new \InvalidArgumentException(sprintf('responseType of type "%s" must implement interface "%s"', $key, $this->responseTypeMap[$key])); |
|
436 | - } |
|
437 | - $this->responseTypes[$key] = $responseType; |
|
438 | - } elseif (!is_null($key) && !is_numeric($key)) { |
|
439 | - throw new \InvalidArgumentException(sprintf('unknown responseType key "%s", must be one of [%s]', $key, implode(', ', array_keys($this->responseTypeMap)))); |
|
440 | - } else { |
|
441 | - $set = false; |
|
442 | - foreach ($this->responseTypeMap as $type => $interface) { |
|
443 | - if ($responseType instanceof $interface) { |
|
444 | - $this->responseTypes[$type] = $responseType; |
|
445 | - $set = true; |
|
446 | - } |
|
447 | - } |
|
448 | - |
|
449 | - if (!$set) { |
|
450 | - throw new \InvalidArgumentException(sprintf('Unknown response type %s. Please implement one of [%s]', get_class($responseType), implode(', ', $this->responseTypeMap))); |
|
451 | - } |
|
452 | - } |
|
453 | - } |
|
454 | - |
|
455 | - public function getScopeUtil() |
|
456 | - { |
|
457 | - if (!$this->scopeUtil) { |
|
458 | - $storage = isset($this->storages['scope']) ? $this->storages['scope'] : null; |
|
459 | - $this->scopeUtil = new Scope($storage); |
|
460 | - } |
|
461 | - |
|
462 | - return $this->scopeUtil; |
|
463 | - } |
|
464 | - |
|
465 | - /** |
|
466 | - * every getter deserves a setter |
|
467 | - */ |
|
468 | - public function setScopeUtil($scopeUtil) |
|
469 | - { |
|
470 | - $this->scopeUtil = $scopeUtil; |
|
471 | - } |
|
472 | - |
|
473 | - protected function createDefaultAuthorizeController() |
|
474 | - { |
|
475 | - if (!isset($this->storages['client'])) { |
|
476 | - throw new \LogicException("You must supply a storage object implementing OAuth2\Storage\ClientInterface to use the authorize server"); |
|
477 | - } |
|
478 | - if (0 == count($this->responseTypes)) { |
|
479 | - $this->responseTypes = $this->getDefaultResponseTypes(); |
|
480 | - } |
|
481 | - if ($this->config['use_openid_connect'] && !isset($this->responseTypes['id_token'])) { |
|
482 | - $this->responseTypes['id_token'] = $this->createDefaultIdTokenResponseType(); |
|
483 | - if ($this->config['allow_implicit']) { |
|
484 | - $this->responseTypes['id_token token'] = $this->createDefaultIdTokenTokenResponseType(); |
|
485 | - } |
|
486 | - } |
|
487 | - |
|
488 | - $config = array_intersect_key($this->config, array_flip(explode(' ', 'allow_implicit enforce_state require_exact_redirect_uri'))); |
|
489 | - |
|
490 | - if ($this->config['use_openid_connect']) { |
|
491 | - return new OpenIDAuthorizeController($this->storages['client'], $this->responseTypes, $config, $this->getScopeUtil()); |
|
492 | - } |
|
493 | - |
|
494 | - return new AuthorizeController($this->storages['client'], $this->responseTypes, $config, $this->getScopeUtil()); |
|
495 | - } |
|
496 | - |
|
497 | - protected function createDefaultTokenController() |
|
498 | - { |
|
499 | - if (0 == count($this->grantTypes)) { |
|
500 | - $this->grantTypes = $this->getDefaultGrantTypes(); |
|
501 | - } |
|
502 | - |
|
503 | - if (is_null($this->clientAssertionType)) { |
|
504 | - // see if HttpBasic assertion type is requred. If so, then create it from storage classes. |
|
505 | - foreach ($this->grantTypes as $grantType) { |
|
506 | - if (!$grantType instanceof ClientAssertionTypeInterface) { |
|
507 | - if (!isset($this->storages['client_credentials'])) { |
|
508 | - throw new \LogicException("You must supply a storage object implementing OAuth2\Storage\ClientCredentialsInterface to use the token server"); |
|
509 | - } |
|
510 | - $config = array_intersect_key($this->config, array_flip(explode(' ', 'allow_credentials_in_request_body allow_public_clients'))); |
|
511 | - $this->clientAssertionType = new HttpBasic($this->storages['client_credentials'], $config); |
|
512 | - break; |
|
513 | - } |
|
514 | - } |
|
515 | - } |
|
516 | - |
|
517 | - if (!isset($this->storages['client'])) { |
|
518 | - throw new \LogicException("You must supply a storage object implementing OAuth2\Storage\ClientInterface to use the token server"); |
|
519 | - } |
|
520 | - |
|
521 | - $accessTokenResponseType = $this->getAccessTokenResponseType(); |
|
522 | - |
|
523 | - return new TokenController($accessTokenResponseType, $this->storages['client'], $this->grantTypes, $this->clientAssertionType, $this->getScopeUtil()); |
|
524 | - } |
|
525 | - |
|
526 | - protected function createDefaultResourceController() |
|
527 | - { |
|
528 | - if ($this->config['use_jwt_access_tokens']) { |
|
529 | - // overwrites access token storage with crypto token storage if "use_jwt_access_tokens" is set |
|
530 | - if (!isset($this->storages['access_token']) || !$this->storages['access_token'] instanceof JwtAccessTokenInterface) { |
|
531 | - $this->storages['access_token'] = $this->createDefaultJwtAccessTokenStorage(); |
|
532 | - } |
|
533 | - } elseif (!isset($this->storages['access_token'])) { |
|
534 | - throw new \LogicException("You must supply a storage object implementing OAuth2\Storage\AccessTokenInterface or use JwtAccessTokens to use the resource server"); |
|
535 | - } |
|
536 | - |
|
537 | - if (!$this->tokenType) { |
|
538 | - $this->tokenType = $this->getDefaultTokenType(); |
|
539 | - } |
|
540 | - |
|
541 | - $config = array_intersect_key($this->config, array('www_realm' => '')); |
|
542 | - |
|
543 | - return new ResourceController($this->tokenType, $this->storages['access_token'], $config, $this->getScopeUtil()); |
|
544 | - } |
|
545 | - |
|
546 | - protected function createDefaultUserInfoController() |
|
547 | - { |
|
548 | - if ($this->config['use_jwt_access_tokens']) { |
|
549 | - // overwrites access token storage with crypto token storage if "use_jwt_access_tokens" is set |
|
550 | - if (!isset($this->storages['access_token']) || !$this->storages['access_token'] instanceof JwtAccessTokenInterface) { |
|
551 | - $this->storages['access_token'] = $this->createDefaultJwtAccessTokenStorage(); |
|
552 | - } |
|
553 | - } elseif (!isset($this->storages['access_token'])) { |
|
554 | - throw new \LogicException("You must supply a storage object implementing OAuth2\Storage\AccessTokenInterface or use JwtAccessTokens to use the UserInfo server"); |
|
555 | - } |
|
556 | - |
|
557 | - if (!isset($this->storages['user_claims'])) { |
|
558 | - throw new \LogicException("You must supply a storage object implementing OAuth2\OpenID\Storage\UserClaimsInterface to use the UserInfo server"); |
|
559 | - } |
|
560 | - |
|
561 | - if (!$this->tokenType) { |
|
562 | - $this->tokenType = $this->getDefaultTokenType(); |
|
563 | - } |
|
564 | - |
|
565 | - $config = array_intersect_key($this->config, array('www_realm' => '')); |
|
566 | - |
|
567 | - return new UserInfoController($this->tokenType, $this->storages['access_token'], $this->storages['user_claims'], $config, $this->getScopeUtil()); |
|
568 | - } |
|
569 | - |
|
570 | - protected function getDefaultTokenType() |
|
571 | - { |
|
572 | - $config = array_intersect_key($this->config, array_flip(explode(' ', 'token_param_name token_bearer_header_name'))); |
|
573 | - |
|
574 | - return new Bearer($config); |
|
575 | - } |
|
576 | - |
|
577 | - protected function getDefaultResponseTypes() |
|
578 | - { |
|
579 | - $responseTypes = array(); |
|
580 | - |
|
581 | - if ($this->config['allow_implicit']) { |
|
582 | - $responseTypes['token'] = $this->getAccessTokenResponseType(); |
|
583 | - } |
|
584 | - |
|
585 | - if ($this->config['use_openid_connect']) { |
|
586 | - $responseTypes['id_token'] = $this->getIdTokenResponseType(); |
|
587 | - if ($this->config['allow_implicit']) { |
|
588 | - $responseTypes['id_token token'] = $this->getIdTokenTokenResponseType(); |
|
589 | - } |
|
590 | - } |
|
591 | - |
|
592 | - if (isset($this->storages['authorization_code'])) { |
|
593 | - $config = array_intersect_key($this->config, array_flip(explode(' ', 'enforce_redirect auth_code_lifetime'))); |
|
594 | - if ($this->config['use_openid_connect']) { |
|
595 | - if (!$this->storages['authorization_code'] instanceof OpenIDAuthorizationCodeInterface) { |
|
596 | - throw new \LogicException("Your authorization_code storage must implement OAuth2\OpenID\Storage\AuthorizationCodeInterface to work when 'use_openid_connect' is true"); |
|
597 | - } |
|
598 | - $responseTypes['code'] = new OpenIDAuthorizationCodeResponseType($this->storages['authorization_code'], $config); |
|
599 | - $responseTypes['code id_token'] = new CodeIdToken($responseTypes['code'], $responseTypes['id_token']); |
|
600 | - } else { |
|
601 | - $responseTypes['code'] = new AuthorizationCodeResponseType($this->storages['authorization_code'], $config); |
|
602 | - } |
|
603 | - } |
|
604 | - |
|
605 | - if (count($responseTypes) == 0) { |
|
606 | - throw new \LogicException("You must supply an array of response_types in the constructor or implement a OAuth2\Storage\AuthorizationCodeInterface storage object or set 'allow_implicit' to true and implement a OAuth2\Storage\AccessTokenInterface storage object"); |
|
607 | - } |
|
608 | - |
|
609 | - return $responseTypes; |
|
610 | - } |
|
611 | - |
|
612 | - protected function getDefaultGrantTypes() |
|
613 | - { |
|
614 | - $grantTypes = array(); |
|
615 | - |
|
616 | - if (isset($this->storages['user_credentials'])) { |
|
617 | - $grantTypes['password'] = new UserCredentials($this->storages['user_credentials']); |
|
618 | - } |
|
619 | - |
|
620 | - if (isset($this->storages['client_credentials'])) { |
|
621 | - $config = array_intersect_key($this->config, array('allow_credentials_in_request_body' => '')); |
|
622 | - $grantTypes['client_credentials'] = new ClientCredentials($this->storages['client_credentials'], $config); |
|
623 | - } |
|
624 | - |
|
625 | - if (isset($this->storages['refresh_token'])) { |
|
626 | - $config = array_intersect_key($this->config, array_flip(explode(' ', 'always_issue_new_refresh_token unset_refresh_token_after_use'))); |
|
627 | - $grantTypes['refresh_token'] = new RefreshToken($this->storages['refresh_token'], $config); |
|
628 | - } |
|
629 | - |
|
630 | - if (isset($this->storages['authorization_code'])) { |
|
631 | - if ($this->config['use_openid_connect']) { |
|
632 | - if (!$this->storages['authorization_code'] instanceof OpenIDAuthorizationCodeInterface) { |
|
633 | - throw new \LogicException("Your authorization_code storage must implement OAuth2\OpenID\Storage\AuthorizationCodeInterface to work when 'use_openid_connect' is true"); |
|
634 | - } |
|
635 | - $grantTypes['authorization_code'] = new OpenIDAuthorizationCodeGrantType($this->storages['authorization_code']); |
|
636 | - } else { |
|
637 | - $grantTypes['authorization_code'] = new AuthorizationCode($this->storages['authorization_code']); |
|
638 | - } |
|
639 | - } |
|
640 | - |
|
641 | - if (count($grantTypes) == 0) { |
|
642 | - throw new \LogicException("Unable to build default grant types - You must supply an array of grant_types in the constructor"); |
|
643 | - } |
|
644 | - |
|
645 | - return $grantTypes; |
|
646 | - } |
|
647 | - |
|
648 | - protected function getAccessTokenResponseType() |
|
649 | - { |
|
650 | - if (isset($this->responseTypes['token'])) { |
|
651 | - return $this->responseTypes['token']; |
|
652 | - } |
|
653 | - |
|
654 | - if ($this->config['use_jwt_access_tokens']) { |
|
655 | - return $this->createDefaultJwtAccessTokenResponseType(); |
|
656 | - } |
|
657 | - |
|
658 | - return $this->createDefaultAccessTokenResponseType(); |
|
659 | - } |
|
660 | - |
|
661 | - protected function getIdTokenResponseType() |
|
662 | - { |
|
663 | - if (isset($this->responseTypes['id_token'])) { |
|
664 | - return $this->responseTypes['id_token']; |
|
665 | - } |
|
666 | - |
|
667 | - return $this->createDefaultIdTokenResponseType(); |
|
668 | - } |
|
669 | - |
|
670 | - protected function getIdTokenTokenResponseType() |
|
671 | - { |
|
672 | - if (isset($this->responseTypes['id_token token'])) { |
|
673 | - return $this->responseTypes['id_token token']; |
|
674 | - } |
|
675 | - |
|
676 | - return $this->createDefaultIdTokenTokenResponseType(); |
|
677 | - } |
|
678 | - |
|
679 | - /** |
|
680 | - * For Resource Controller |
|
681 | - */ |
|
682 | - protected function createDefaultJwtAccessTokenStorage() |
|
683 | - { |
|
684 | - if (!isset($this->storages['public_key'])) { |
|
685 | - throw new \LogicException("You must supply a storage object implementing OAuth2\Storage\PublicKeyInterface to use crypto tokens"); |
|
686 | - } |
|
687 | - $tokenStorage = null; |
|
688 | - if (!empty($this->config['store_encrypted_token_string']) && isset($this->storages['access_token'])) { |
|
689 | - $tokenStorage = $this->storages['access_token']; |
|
690 | - } |
|
691 | - // wrap the access token storage as required. |
|
692 | - return new JwtAccessTokenStorage($this->storages['public_key'], $tokenStorage); |
|
693 | - } |
|
694 | - |
|
695 | - /** |
|
696 | - * For Authorize and Token Controllers |
|
697 | - */ |
|
698 | - protected function createDefaultJwtAccessTokenResponseType() |
|
699 | - { |
|
700 | - if (!isset($this->storages['public_key'])) { |
|
701 | - throw new \LogicException("You must supply a storage object implementing OAuth2\Storage\PublicKeyInterface to use crypto tokens"); |
|
702 | - } |
|
703 | - |
|
704 | - $tokenStorage = null; |
|
705 | - if (isset($this->storages['access_token'])) { |
|
706 | - $tokenStorage = $this->storages['access_token']; |
|
707 | - } |
|
708 | - |
|
709 | - $refreshStorage = null; |
|
710 | - if (isset($this->storages['refresh_token'])) { |
|
711 | - $refreshStorage = $this->storages['refresh_token']; |
|
712 | - } |
|
713 | - |
|
714 | - $config = array_intersect_key($this->config, array_flip(explode(' ', 'store_encrypted_token_string issuer access_lifetime refresh_token_lifetime'))); |
|
715 | - |
|
716 | - return new JwtAccessToken($this->storages['public_key'], $tokenStorage, $refreshStorage, $config); |
|
717 | - } |
|
718 | - |
|
719 | - protected function createDefaultAccessTokenResponseType() |
|
720 | - { |
|
721 | - if (!isset($this->storages['access_token'])) { |
|
722 | - throw new \LogicException("You must supply a response type implementing OAuth2\ResponseType\AccessTokenInterface, or a storage object implementing OAuth2\Storage\AccessTokenInterface to use the token server"); |
|
723 | - } |
|
724 | - |
|
725 | - $refreshStorage = null; |
|
726 | - if (isset($this->storages['refresh_token'])) { |
|
727 | - $refreshStorage = $this->storages['refresh_token']; |
|
728 | - } |
|
729 | - |
|
730 | - $config = array_intersect_key($this->config, array_flip(explode(' ', 'access_lifetime refresh_token_lifetime'))); |
|
731 | - $config['token_type'] = $this->tokenType ? $this->tokenType->getTokenType() : $this->getDefaultTokenType()->getTokenType(); |
|
732 | - |
|
733 | - return new AccessToken($this->storages['access_token'], $refreshStorage, $config); |
|
734 | - } |
|
735 | - |
|
736 | - protected function createDefaultIdTokenResponseType() |
|
737 | - { |
|
738 | - if (!isset($this->storages['user_claims'])) { |
|
739 | - throw new \LogicException("You must supply a storage object implementing OAuth2\OpenID\Storage\UserClaimsInterface to use openid connect"); |
|
740 | - } |
|
741 | - if (!isset($this->storages['public_key'])) { |
|
742 | - throw new \LogicException("You must supply a storage object implementing OAuth2\Storage\PublicKeyInterface to use openid connect"); |
|
743 | - } |
|
744 | - |
|
745 | - $config = array_intersect_key($this->config, array_flip(explode(' ', 'issuer id_lifetime'))); |
|
746 | - |
|
747 | - return new IdToken($this->storages['user_claims'], $this->storages['public_key'], $config); |
|
748 | - } |
|
749 | - |
|
750 | - protected function createDefaultIdTokenTokenResponseType() |
|
751 | - { |
|
752 | - return new IdTokenToken($this->getAccessTokenResponseType(), $this->getIdTokenResponseType()); |
|
753 | - } |
|
754 | - |
|
755 | - protected function validateOpenIdConnect() |
|
756 | - { |
|
757 | - $authCodeGrant = $this->getGrantType('authorization_code'); |
|
758 | - if (!empty($authCodeGrant) && !$authCodeGrant instanceof OpenIDAuthorizationCodeGrantType) { |
|
759 | - throw new \InvalidArgumentException('You have enabled OpenID Connect, but supplied a grant type that does not support it.'); |
|
760 | - } |
|
761 | - } |
|
762 | - |
|
763 | - protected function normalizeResponseType($name) |
|
764 | - { |
|
765 | - // for multiple-valued response types - make them alphabetical |
|
766 | - if (!empty($name) && false !== strpos($name, ' ')) { |
|
767 | - $types = explode(' ', $name); |
|
768 | - sort($types); |
|
769 | - $name = implode(' ', $types); |
|
770 | - } |
|
771 | - |
|
772 | - return $name; |
|
773 | - } |
|
774 | - |
|
775 | - public function getResponse() |
|
776 | - { |
|
777 | - return $this->response; |
|
778 | - } |
|
779 | - |
|
780 | - public function getStorages() |
|
781 | - { |
|
782 | - return $this->storages; |
|
783 | - } |
|
784 | - |
|
785 | - public function getStorage($name) |
|
786 | - { |
|
787 | - return isset($this->storages[$name]) ? $this->storages[$name] : null; |
|
788 | - } |
|
789 | - |
|
790 | - public function getGrantTypes() |
|
791 | - { |
|
792 | - return $this->grantTypes; |
|
793 | - } |
|
794 | - |
|
795 | - public function getGrantType($name) |
|
796 | - { |
|
797 | - return isset($this->grantTypes[$name]) ? $this->grantTypes[$name] : null; |
|
798 | - } |
|
799 | - |
|
800 | - public function getResponseTypes() |
|
801 | - { |
|
802 | - return $this->responseTypes; |
|
803 | - } |
|
804 | - |
|
805 | - public function getResponseType($name) |
|
806 | - { |
|
807 | - // for multiple-valued response types - make them alphabetical |
|
808 | - $name = $this->normalizeResponseType($name); |
|
809 | - |
|
810 | - return isset($this->responseTypes[$name]) ? $this->responseTypes[$name] : null; |
|
811 | - } |
|
812 | - |
|
813 | - public function getTokenType() |
|
814 | - { |
|
815 | - return $this->tokenType; |
|
816 | - } |
|
817 | - |
|
818 | - public function getClientAssertionType() |
|
819 | - { |
|
820 | - return $this->clientAssertionType; |
|
821 | - } |
|
822 | - |
|
823 | - public function setConfig($name, $value) |
|
824 | - { |
|
825 | - $this->config[$name] = $value; |
|
826 | - } |
|
827 | - |
|
828 | - public function getConfig($name, $default = null) |
|
829 | - { |
|
830 | - return isset($this->config[$name]) ? $this->config[$name] : $default; |
|
831 | - } |
|
49 | + // misc properties |
|
50 | + protected $response; |
|
51 | + protected $config; |
|
52 | + protected $storages; |
|
53 | + |
|
54 | + // servers |
|
55 | + protected $authorizeController; |
|
56 | + protected $tokenController; |
|
57 | + protected $resourceController; |
|
58 | + protected $userInfoController; |
|
59 | + |
|
60 | + // config classes |
|
61 | + protected $grantTypes; |
|
62 | + protected $responseTypes; |
|
63 | + protected $tokenType; |
|
64 | + protected $scopeUtil; |
|
65 | + protected $clientAssertionType; |
|
66 | + |
|
67 | + protected $storageMap = array( |
|
68 | + 'access_token' => 'OAuth2\Storage\AccessTokenInterface', |
|
69 | + 'authorization_code' => 'OAuth2\Storage\AuthorizationCodeInterface', |
|
70 | + 'client_credentials' => 'OAuth2\Storage\ClientCredentialsInterface', |
|
71 | + 'client' => 'OAuth2\Storage\ClientInterface', |
|
72 | + 'refresh_token' => 'OAuth2\Storage\RefreshTokenInterface', |
|
73 | + 'user_credentials' => 'OAuth2\Storage\UserCredentialsInterface', |
|
74 | + 'user_claims' => 'OAuth2\OpenID\Storage\UserClaimsInterface', |
|
75 | + 'public_key' => 'OAuth2\Storage\PublicKeyInterface', |
|
76 | + 'jwt_bearer' => 'OAuth2\Storage\JWTBearerInterface', |
|
77 | + 'scope' => 'OAuth2\Storage\ScopeInterface', |
|
78 | + ); |
|
79 | + |
|
80 | + protected $responseTypeMap = array( |
|
81 | + 'token' => 'OAuth2\ResponseType\AccessTokenInterface', |
|
82 | + 'code' => 'OAuth2\ResponseType\AuthorizationCodeInterface', |
|
83 | + 'id_token' => 'OAuth2\OpenID\ResponseType\IdTokenInterface', |
|
84 | + 'id_token token' => 'OAuth2\OpenID\ResponseType\IdTokenTokenInterface', |
|
85 | + 'code id_token' => 'OAuth2\OpenID\ResponseType\CodeIdTokenInterface', |
|
86 | + ); |
|
87 | + |
|
88 | + /** |
|
89 | + * @param mixed $storage (array or OAuth2\Storage) - single object or array of objects implementing the |
|
90 | + * required storage types (ClientCredentialsInterface and AccessTokenInterface as a minimum) |
|
91 | + * @param array $config specify a different token lifetime, token header name, etc |
|
92 | + * @param array $grantTypes An array of OAuth2\GrantType\GrantTypeInterface to use for granting access tokens |
|
93 | + * @param array $responseTypes Response types to use. array keys should be "code" and and "token" for |
|
94 | + * Access Token and Authorization Code response types |
|
95 | + * @param OAuth2\TokenType\TokenTypeInterface $tokenType The token type object to use. Valid token types are "bearer" and "mac" |
|
96 | + * @param OAuth2\ScopeInterface $scopeUtil The scope utility class to use to validate scope |
|
97 | + * @param OAuth2\ClientAssertionType\ClientAssertionTypeInterface $clientAssertionType The method in which to verify the client identity. Default is HttpBasic |
|
98 | + * |
|
99 | + * @ingroup oauth2_section_7 |
|
100 | + */ |
|
101 | + public function __construct($storage = array(), array $config = array(), array $grantTypes = array(), array $responseTypes = array(), TokenTypeInterface $tokenType = null, ScopeInterface $scopeUtil = null, ClientAssertionTypeInterface $clientAssertionType = null) |
|
102 | + { |
|
103 | + $storage = is_array($storage) ? $storage : array($storage); |
|
104 | + $this->storages = array(); |
|
105 | + foreach ($storage as $key => $service) { |
|
106 | + $this->addStorage($service, $key); |
|
107 | + } |
|
108 | + |
|
109 | + // merge all config values. These get passed to our controller objects |
|
110 | + $this->config = array_merge(array( |
|
111 | + 'use_jwt_access_tokens' => false, |
|
112 | + 'store_encrypted_token_string' => true, |
|
113 | + 'use_openid_connect' => false, |
|
114 | + 'id_lifetime' => 3600, |
|
115 | + 'access_lifetime' => 3600, |
|
116 | + 'www_realm' => 'Service', |
|
117 | + 'token_param_name' => 'access_token', |
|
118 | + 'token_bearer_header_name' => 'Bearer', |
|
119 | + 'enforce_state' => true, |
|
120 | + 'require_exact_redirect_uri' => true, |
|
121 | + 'allow_implicit' => false, |
|
122 | + 'allow_credentials_in_request_body' => true, |
|
123 | + 'allow_public_clients' => true, |
|
124 | + 'always_issue_new_refresh_token' => false, |
|
125 | + 'unset_refresh_token_after_use' => true, |
|
126 | + ), $config); |
|
127 | + |
|
128 | + foreach ($grantTypes as $key => $grantType) { |
|
129 | + $this->addGrantType($grantType, $key); |
|
130 | + } |
|
131 | + |
|
132 | + foreach ($responseTypes as $key => $responseType) { |
|
133 | + $this->addResponseType($responseType, $key); |
|
134 | + } |
|
135 | + |
|
136 | + $this->tokenType = $tokenType; |
|
137 | + $this->scopeUtil = $scopeUtil; |
|
138 | + $this->clientAssertionType = $clientAssertionType; |
|
139 | + |
|
140 | + if ($this->config['use_openid_connect']) { |
|
141 | + $this->validateOpenIdConnect(); |
|
142 | + } |
|
143 | + } |
|
144 | + |
|
145 | + public function getAuthorizeController() |
|
146 | + { |
|
147 | + if (is_null($this->authorizeController)) { |
|
148 | + $this->authorizeController = $this->createDefaultAuthorizeController(); |
|
149 | + } |
|
150 | + |
|
151 | + return $this->authorizeController; |
|
152 | + } |
|
153 | + |
|
154 | + public function getTokenController() |
|
155 | + { |
|
156 | + if (is_null($this->tokenController)) { |
|
157 | + $this->tokenController = $this->createDefaultTokenController(); |
|
158 | + } |
|
159 | + |
|
160 | + return $this->tokenController; |
|
161 | + } |
|
162 | + |
|
163 | + public function getResourceController() |
|
164 | + { |
|
165 | + if (is_null($this->resourceController)) { |
|
166 | + $this->resourceController = $this->createDefaultResourceController(); |
|
167 | + } |
|
168 | + |
|
169 | + return $this->resourceController; |
|
170 | + } |
|
171 | + |
|
172 | + public function getUserInfoController() |
|
173 | + { |
|
174 | + if (is_null($this->userInfoController)) { |
|
175 | + $this->userInfoController = $this->createDefaultUserInfoController(); |
|
176 | + } |
|
177 | + |
|
178 | + return $this->userInfoController; |
|
179 | + } |
|
180 | + |
|
181 | + /** |
|
182 | + * every getter deserves a setter |
|
183 | + */ |
|
184 | + public function setAuthorizeController(AuthorizeControllerInterface $authorizeController) |
|
185 | + { |
|
186 | + $this->authorizeController = $authorizeController; |
|
187 | + } |
|
188 | + |
|
189 | + /** |
|
190 | + * every getter deserves a setter |
|
191 | + */ |
|
192 | + public function setTokenController(TokenControllerInterface $tokenController) |
|
193 | + { |
|
194 | + $this->tokenController = $tokenController; |
|
195 | + } |
|
196 | + |
|
197 | + /** |
|
198 | + * every getter deserves a setter |
|
199 | + */ |
|
200 | + public function setResourceController(ResourceControllerInterface $resourceController) |
|
201 | + { |
|
202 | + $this->resourceController = $resourceController; |
|
203 | + } |
|
204 | + |
|
205 | + /** |
|
206 | + * every getter deserves a setter |
|
207 | + */ |
|
208 | + public function setUserInfoController(UserInfoControllerInterface $userInfoController) |
|
209 | + { |
|
210 | + $this->userInfoController = $userInfoController; |
|
211 | + } |
|
212 | + |
|
213 | + /** |
|
214 | + * Return claims about the authenticated end-user. |
|
215 | + * This would be called from the "/UserInfo" endpoint as defined in the spec. |
|
216 | + * |
|
217 | + * @param $request - OAuth2\RequestInterface |
|
218 | + * Request object to grant access token |
|
219 | + * |
|
220 | + * @param $response - OAuth2\ResponseInterface |
|
221 | + * Response object containing error messages (failure) or user claims (success) |
|
222 | + * |
|
223 | + * @throws InvalidArgumentException |
|
224 | + * @throws LogicException |
|
225 | + * |
|
226 | + * @see http://openid.net/specs/openid-connect-core-1_0.html#UserInfo |
|
227 | + */ |
|
228 | + public function handleUserInfoRequest(RequestInterface $request, ResponseInterface $response = null) |
|
229 | + { |
|
230 | + $this->response = is_null($response) ? new Response() : $response; |
|
231 | + $this->getUserInfoController()->handleUserInfoRequest($request, $this->response); |
|
232 | + |
|
233 | + return $this->response; |
|
234 | + } |
|
235 | + |
|
236 | + /** |
|
237 | + * Grant or deny a requested access token. |
|
238 | + * This would be called from the "/token" endpoint as defined in the spec. |
|
239 | + * Obviously, you can call your endpoint whatever you want. |
|
240 | + * |
|
241 | + * @param $request - OAuth2\RequestInterface |
|
242 | + * Request object to grant access token |
|
243 | + * |
|
244 | + * @param $response - OAuth2\ResponseInterface |
|
245 | + * Response object containing error messages (failure) or access token (success) |
|
246 | + * |
|
247 | + * @throws InvalidArgumentException |
|
248 | + * @throws LogicException |
|
249 | + * |
|
250 | + * @see http://tools.ietf.org/html/rfc6749#section-4 |
|
251 | + * @see http://tools.ietf.org/html/rfc6749#section-10.6 |
|
252 | + * @see http://tools.ietf.org/html/rfc6749#section-4.1.3 |
|
253 | + * |
|
254 | + * @ingroup oauth2_section_4 |
|
255 | + */ |
|
256 | + public function handleTokenRequest(RequestInterface $request, ResponseInterface $response = null) |
|
257 | + { |
|
258 | + $this->response = is_null($response) ? new Response() : $response; |
|
259 | + $this->getTokenController()->handleTokenRequest($request, $this->response); |
|
260 | + |
|
261 | + return $this->response; |
|
262 | + } |
|
263 | + |
|
264 | + public function grantAccessToken(RequestInterface $request, ResponseInterface $response = null) |
|
265 | + { |
|
266 | + $this->response = is_null($response) ? new Response() : $response; |
|
267 | + $value = $this->getTokenController()->grantAccessToken($request, $this->response); |
|
268 | + |
|
269 | + return $value; |
|
270 | + } |
|
271 | + |
|
272 | + /** |
|
273 | + * Handle a revoke token request |
|
274 | + * This would be called from the "/revoke" endpoint as defined in the draft Token Revocation spec |
|
275 | + * |
|
276 | + * @see https://tools.ietf.org/html/rfc7009#section-2 |
|
277 | + * |
|
278 | + * @param RequestInterface $request |
|
279 | + * @param ResponseInterface $response |
|
280 | + * @return Response|ResponseInterface |
|
281 | + */ |
|
282 | + public function handleRevokeRequest(RequestInterface $request, ResponseInterface $response = null) |
|
283 | + { |
|
284 | + $this->response = is_null($response) ? new Response() : $response; |
|
285 | + $this->getTokenController()->handleRevokeRequest($request, $this->response); |
|
286 | + |
|
287 | + return $this->response; |
|
288 | + } |
|
289 | + |
|
290 | + /** |
|
291 | + * Redirect the user appropriately after approval. |
|
292 | + * |
|
293 | + * After the user has approved or denied the resource request the |
|
294 | + * authorization server should call this function to redirect the user |
|
295 | + * appropriately. |
|
296 | + * |
|
297 | + * @param $request |
|
298 | + * The request should have the follow parameters set in the querystring: |
|
299 | + * - response_type: The requested response: an access token, an |
|
300 | + * authorization code, or both. |
|
301 | + * - client_id: The client identifier as described in Section 2. |
|
302 | + * - redirect_uri: An absolute URI to which the authorization server |
|
303 | + * will redirect the user-agent to when the end-user authorization |
|
304 | + * step is completed. |
|
305 | + * - scope: (optional) The scope of the resource request expressed as a |
|
306 | + * list of space-delimited strings. |
|
307 | + * - state: (optional) An opaque value used by the client to maintain |
|
308 | + * state between the request and callback. |
|
309 | + * @param $is_authorized |
|
310 | + * TRUE or FALSE depending on whether the user authorized the access. |
|
311 | + * @param $user_id |
|
312 | + * Identifier of user who authorized the client |
|
313 | + * |
|
314 | + * @see http://tools.ietf.org/html/rfc6749#section-4 |
|
315 | + * |
|
316 | + * @ingroup oauth2_section_4 |
|
317 | + */ |
|
318 | + public function handleAuthorizeRequest(RequestInterface $request, ResponseInterface $response, $is_authorized, $user_id = null) |
|
319 | + { |
|
320 | + $this->response = $response; |
|
321 | + $this->getAuthorizeController()->handleAuthorizeRequest($request, $this->response, $is_authorized, $user_id); |
|
322 | + |
|
323 | + return $this->response; |
|
324 | + } |
|
325 | + |
|
326 | + /** |
|
327 | + * Pull the authorization request data out of the HTTP request. |
|
328 | + * - The redirect_uri is OPTIONAL as per draft 20. But your implementation can enforce it |
|
329 | + * by setting $config['enforce_redirect'] to true. |
|
330 | + * - The state is OPTIONAL but recommended to enforce CSRF. Draft 21 states, however, that |
|
331 | + * CSRF protection is MANDATORY. You can enforce this by setting the $config['enforce_state'] to true. |
|
332 | + * |
|
333 | + * The draft specifies that the parameters should be retrieved from GET, override the Response |
|
334 | + * object to change this |
|
335 | + * |
|
336 | + * @return |
|
337 | + * The authorization parameters so the authorization server can prompt |
|
338 | + * the user for approval if valid. |
|
339 | + * |
|
340 | + * @see http://tools.ietf.org/html/rfc6749#section-4.1.1 |
|
341 | + * @see http://tools.ietf.org/html/rfc6749#section-10.12 |
|
342 | + * |
|
343 | + * @ingroup oauth2_section_3 |
|
344 | + */ |
|
345 | + public function validateAuthorizeRequest(RequestInterface $request, ResponseInterface $response = null) |
|
346 | + { |
|
347 | + $this->response = is_null($response) ? new Response() : $response; |
|
348 | + $value = $this->getAuthorizeController()->validateAuthorizeRequest($request, $this->response); |
|
349 | + |
|
350 | + return $value; |
|
351 | + } |
|
352 | + |
|
353 | + public function verifyResourceRequest(RequestInterface $request, ResponseInterface $response = null, $scope = null) |
|
354 | + { |
|
355 | + $this->response = is_null($response) ? new Response() : $response; |
|
356 | + $value = $this->getResourceController()->verifyResourceRequest($request, $this->response, $scope); |
|
357 | + |
|
358 | + return $value; |
|
359 | + } |
|
360 | + |
|
361 | + public function getAccessTokenData(RequestInterface $request, ResponseInterface $response = null) |
|
362 | + { |
|
363 | + $this->response = is_null($response) ? new Response() : $response; |
|
364 | + $value = $this->getResourceController()->getAccessTokenData($request, $this->response); |
|
365 | + |
|
366 | + return $value; |
|
367 | + } |
|
368 | + |
|
369 | + public function addGrantType(GrantTypeInterface $grantType, $identifier = null) |
|
370 | + { |
|
371 | + if (!is_string($identifier)) { |
|
372 | + $identifier = $grantType->getQuerystringIdentifier(); |
|
373 | + } |
|
374 | + |
|
375 | + $this->grantTypes[$identifier] = $grantType; |
|
376 | + |
|
377 | + // persist added grant type down to TokenController |
|
378 | + if (!is_null($this->tokenController)) { |
|
379 | + $this->getTokenController()->addGrantType($grantType, $identifier); |
|
380 | + } |
|
381 | + } |
|
382 | + |
|
383 | + /** |
|
384 | + * Set a storage object for the server |
|
385 | + * |
|
386 | + * @param $storage |
|
387 | + * An object implementing one of the Storage interfaces |
|
388 | + * @param $key |
|
389 | + * If null, the storage is set to the key of each storage interface it implements |
|
390 | + * |
|
391 | + * @see storageMap |
|
392 | + */ |
|
393 | + public function addStorage($storage, $key = null) |
|
394 | + { |
|
395 | + // if explicitly set to a valid key, do not "magically" set below |
|
396 | + if (isset($this->storageMap[$key])) { |
|
397 | + if (!is_null($storage) && !$storage instanceof $this->storageMap[$key]) { |
|
398 | + throw new \InvalidArgumentException(sprintf('storage of type "%s" must implement interface "%s"', $key, $this->storageMap[$key])); |
|
399 | + } |
|
400 | + $this->storages[$key] = $storage; |
|
401 | + |
|
402 | + // special logic to handle "client" and "client_credentials" strangeness |
|
403 | + if ($key === 'client' && !isset($this->storages['client_credentials'])) { |
|
404 | + if ($storage instanceof \OAuth2\Storage\ClientCredentialsInterface) { |
|
405 | + $this->storages['client_credentials'] = $storage; |
|
406 | + } |
|
407 | + } elseif ($key === 'client_credentials' && !isset($this->storages['client'])) { |
|
408 | + if ($storage instanceof \OAuth2\Storage\ClientInterface) { |
|
409 | + $this->storages['client'] = $storage; |
|
410 | + } |
|
411 | + } |
|
412 | + } elseif (!is_null($key) && !is_numeric($key)) { |
|
413 | + throw new \InvalidArgumentException(sprintf('unknown storage key "%s", must be one of [%s]', $key, implode(', ', array_keys($this->storageMap)))); |
|
414 | + } else { |
|
415 | + $set = false; |
|
416 | + foreach ($this->storageMap as $type => $interface) { |
|
417 | + if ($storage instanceof $interface) { |
|
418 | + $this->storages[$type] = $storage; |
|
419 | + $set = true; |
|
420 | + } |
|
421 | + } |
|
422 | + |
|
423 | + if (!$set) { |
|
424 | + throw new \InvalidArgumentException(sprintf('storage of class "%s" must implement one of [%s]', get_class($storage), implode(', ', $this->storageMap))); |
|
425 | + } |
|
426 | + } |
|
427 | + } |
|
428 | + |
|
429 | + public function addResponseType(ResponseTypeInterface $responseType, $key = null) |
|
430 | + { |
|
431 | + $key = $this->normalizeResponseType($key); |
|
432 | + |
|
433 | + if (isset($this->responseTypeMap[$key])) { |
|
434 | + if (!$responseType instanceof $this->responseTypeMap[$key]) { |
|
435 | + throw new \InvalidArgumentException(sprintf('responseType of type "%s" must implement interface "%s"', $key, $this->responseTypeMap[$key])); |
|
436 | + } |
|
437 | + $this->responseTypes[$key] = $responseType; |
|
438 | + } elseif (!is_null($key) && !is_numeric($key)) { |
|
439 | + throw new \InvalidArgumentException(sprintf('unknown responseType key "%s", must be one of [%s]', $key, implode(', ', array_keys($this->responseTypeMap)))); |
|
440 | + } else { |
|
441 | + $set = false; |
|
442 | + foreach ($this->responseTypeMap as $type => $interface) { |
|
443 | + if ($responseType instanceof $interface) { |
|
444 | + $this->responseTypes[$type] = $responseType; |
|
445 | + $set = true; |
|
446 | + } |
|
447 | + } |
|
448 | + |
|
449 | + if (!$set) { |
|
450 | + throw new \InvalidArgumentException(sprintf('Unknown response type %s. Please implement one of [%s]', get_class($responseType), implode(', ', $this->responseTypeMap))); |
|
451 | + } |
|
452 | + } |
|
453 | + } |
|
454 | + |
|
455 | + public function getScopeUtil() |
|
456 | + { |
|
457 | + if (!$this->scopeUtil) { |
|
458 | + $storage = isset($this->storages['scope']) ? $this->storages['scope'] : null; |
|
459 | + $this->scopeUtil = new Scope($storage); |
|
460 | + } |
|
461 | + |
|
462 | + return $this->scopeUtil; |
|
463 | + } |
|
464 | + |
|
465 | + /** |
|
466 | + * every getter deserves a setter |
|
467 | + */ |
|
468 | + public function setScopeUtil($scopeUtil) |
|
469 | + { |
|
470 | + $this->scopeUtil = $scopeUtil; |
|
471 | + } |
|
472 | + |
|
473 | + protected function createDefaultAuthorizeController() |
|
474 | + { |
|
475 | + if (!isset($this->storages['client'])) { |
|
476 | + throw new \LogicException("You must supply a storage object implementing OAuth2\Storage\ClientInterface to use the authorize server"); |
|
477 | + } |
|
478 | + if (0 == count($this->responseTypes)) { |
|
479 | + $this->responseTypes = $this->getDefaultResponseTypes(); |
|
480 | + } |
|
481 | + if ($this->config['use_openid_connect'] && !isset($this->responseTypes['id_token'])) { |
|
482 | + $this->responseTypes['id_token'] = $this->createDefaultIdTokenResponseType(); |
|
483 | + if ($this->config['allow_implicit']) { |
|
484 | + $this->responseTypes['id_token token'] = $this->createDefaultIdTokenTokenResponseType(); |
|
485 | + } |
|
486 | + } |
|
487 | + |
|
488 | + $config = array_intersect_key($this->config, array_flip(explode(' ', 'allow_implicit enforce_state require_exact_redirect_uri'))); |
|
489 | + |
|
490 | + if ($this->config['use_openid_connect']) { |
|
491 | + return new OpenIDAuthorizeController($this->storages['client'], $this->responseTypes, $config, $this->getScopeUtil()); |
|
492 | + } |
|
493 | + |
|
494 | + return new AuthorizeController($this->storages['client'], $this->responseTypes, $config, $this->getScopeUtil()); |
|
495 | + } |
|
496 | + |
|
497 | + protected function createDefaultTokenController() |
|
498 | + { |
|
499 | + if (0 == count($this->grantTypes)) { |
|
500 | + $this->grantTypes = $this->getDefaultGrantTypes(); |
|
501 | + } |
|
502 | + |
|
503 | + if (is_null($this->clientAssertionType)) { |
|
504 | + // see if HttpBasic assertion type is requred. If so, then create it from storage classes. |
|
505 | + foreach ($this->grantTypes as $grantType) { |
|
506 | + if (!$grantType instanceof ClientAssertionTypeInterface) { |
|
507 | + if (!isset($this->storages['client_credentials'])) { |
|
508 | + throw new \LogicException("You must supply a storage object implementing OAuth2\Storage\ClientCredentialsInterface to use the token server"); |
|
509 | + } |
|
510 | + $config = array_intersect_key($this->config, array_flip(explode(' ', 'allow_credentials_in_request_body allow_public_clients'))); |
|
511 | + $this->clientAssertionType = new HttpBasic($this->storages['client_credentials'], $config); |
|
512 | + break; |
|
513 | + } |
|
514 | + } |
|
515 | + } |
|
516 | + |
|
517 | + if (!isset($this->storages['client'])) { |
|
518 | + throw new \LogicException("You must supply a storage object implementing OAuth2\Storage\ClientInterface to use the token server"); |
|
519 | + } |
|
520 | + |
|
521 | + $accessTokenResponseType = $this->getAccessTokenResponseType(); |
|
522 | + |
|
523 | + return new TokenController($accessTokenResponseType, $this->storages['client'], $this->grantTypes, $this->clientAssertionType, $this->getScopeUtil()); |
|
524 | + } |
|
525 | + |
|
526 | + protected function createDefaultResourceController() |
|
527 | + { |
|
528 | + if ($this->config['use_jwt_access_tokens']) { |
|
529 | + // overwrites access token storage with crypto token storage if "use_jwt_access_tokens" is set |
|
530 | + if (!isset($this->storages['access_token']) || !$this->storages['access_token'] instanceof JwtAccessTokenInterface) { |
|
531 | + $this->storages['access_token'] = $this->createDefaultJwtAccessTokenStorage(); |
|
532 | + } |
|
533 | + } elseif (!isset($this->storages['access_token'])) { |
|
534 | + throw new \LogicException("You must supply a storage object implementing OAuth2\Storage\AccessTokenInterface or use JwtAccessTokens to use the resource server"); |
|
535 | + } |
|
536 | + |
|
537 | + if (!$this->tokenType) { |
|
538 | + $this->tokenType = $this->getDefaultTokenType(); |
|
539 | + } |
|
540 | + |
|
541 | + $config = array_intersect_key($this->config, array('www_realm' => '')); |
|
542 | + |
|
543 | + return new ResourceController($this->tokenType, $this->storages['access_token'], $config, $this->getScopeUtil()); |
|
544 | + } |
|
545 | + |
|
546 | + protected function createDefaultUserInfoController() |
|
547 | + { |
|
548 | + if ($this->config['use_jwt_access_tokens']) { |
|
549 | + // overwrites access token storage with crypto token storage if "use_jwt_access_tokens" is set |
|
550 | + if (!isset($this->storages['access_token']) || !$this->storages['access_token'] instanceof JwtAccessTokenInterface) { |
|
551 | + $this->storages['access_token'] = $this->createDefaultJwtAccessTokenStorage(); |
|
552 | + } |
|
553 | + } elseif (!isset($this->storages['access_token'])) { |
|
554 | + throw new \LogicException("You must supply a storage object implementing OAuth2\Storage\AccessTokenInterface or use JwtAccessTokens to use the UserInfo server"); |
|
555 | + } |
|
556 | + |
|
557 | + if (!isset($this->storages['user_claims'])) { |
|
558 | + throw new \LogicException("You must supply a storage object implementing OAuth2\OpenID\Storage\UserClaimsInterface to use the UserInfo server"); |
|
559 | + } |
|
560 | + |
|
561 | + if (!$this->tokenType) { |
|
562 | + $this->tokenType = $this->getDefaultTokenType(); |
|
563 | + } |
|
564 | + |
|
565 | + $config = array_intersect_key($this->config, array('www_realm' => '')); |
|
566 | + |
|
567 | + return new UserInfoController($this->tokenType, $this->storages['access_token'], $this->storages['user_claims'], $config, $this->getScopeUtil()); |
|
568 | + } |
|
569 | + |
|
570 | + protected function getDefaultTokenType() |
|
571 | + { |
|
572 | + $config = array_intersect_key($this->config, array_flip(explode(' ', 'token_param_name token_bearer_header_name'))); |
|
573 | + |
|
574 | + return new Bearer($config); |
|
575 | + } |
|
576 | + |
|
577 | + protected function getDefaultResponseTypes() |
|
578 | + { |
|
579 | + $responseTypes = array(); |
|
580 | + |
|
581 | + if ($this->config['allow_implicit']) { |
|
582 | + $responseTypes['token'] = $this->getAccessTokenResponseType(); |
|
583 | + } |
|
584 | + |
|
585 | + if ($this->config['use_openid_connect']) { |
|
586 | + $responseTypes['id_token'] = $this->getIdTokenResponseType(); |
|
587 | + if ($this->config['allow_implicit']) { |
|
588 | + $responseTypes['id_token token'] = $this->getIdTokenTokenResponseType(); |
|
589 | + } |
|
590 | + } |
|
591 | + |
|
592 | + if (isset($this->storages['authorization_code'])) { |
|
593 | + $config = array_intersect_key($this->config, array_flip(explode(' ', 'enforce_redirect auth_code_lifetime'))); |
|
594 | + if ($this->config['use_openid_connect']) { |
|
595 | + if (!$this->storages['authorization_code'] instanceof OpenIDAuthorizationCodeInterface) { |
|
596 | + throw new \LogicException("Your authorization_code storage must implement OAuth2\OpenID\Storage\AuthorizationCodeInterface to work when 'use_openid_connect' is true"); |
|
597 | + } |
|
598 | + $responseTypes['code'] = new OpenIDAuthorizationCodeResponseType($this->storages['authorization_code'], $config); |
|
599 | + $responseTypes['code id_token'] = new CodeIdToken($responseTypes['code'], $responseTypes['id_token']); |
|
600 | + } else { |
|
601 | + $responseTypes['code'] = new AuthorizationCodeResponseType($this->storages['authorization_code'], $config); |
|
602 | + } |
|
603 | + } |
|
604 | + |
|
605 | + if (count($responseTypes) == 0) { |
|
606 | + throw new \LogicException("You must supply an array of response_types in the constructor or implement a OAuth2\Storage\AuthorizationCodeInterface storage object or set 'allow_implicit' to true and implement a OAuth2\Storage\AccessTokenInterface storage object"); |
|
607 | + } |
|
608 | + |
|
609 | + return $responseTypes; |
|
610 | + } |
|
611 | + |
|
612 | + protected function getDefaultGrantTypes() |
|
613 | + { |
|
614 | + $grantTypes = array(); |
|
615 | + |
|
616 | + if (isset($this->storages['user_credentials'])) { |
|
617 | + $grantTypes['password'] = new UserCredentials($this->storages['user_credentials']); |
|
618 | + } |
|
619 | + |
|
620 | + if (isset($this->storages['client_credentials'])) { |
|
621 | + $config = array_intersect_key($this->config, array('allow_credentials_in_request_body' => '')); |
|
622 | + $grantTypes['client_credentials'] = new ClientCredentials($this->storages['client_credentials'], $config); |
|
623 | + } |
|
624 | + |
|
625 | + if (isset($this->storages['refresh_token'])) { |
|
626 | + $config = array_intersect_key($this->config, array_flip(explode(' ', 'always_issue_new_refresh_token unset_refresh_token_after_use'))); |
|
627 | + $grantTypes['refresh_token'] = new RefreshToken($this->storages['refresh_token'], $config); |
|
628 | + } |
|
629 | + |
|
630 | + if (isset($this->storages['authorization_code'])) { |
|
631 | + if ($this->config['use_openid_connect']) { |
|
632 | + if (!$this->storages['authorization_code'] instanceof OpenIDAuthorizationCodeInterface) { |
|
633 | + throw new \LogicException("Your authorization_code storage must implement OAuth2\OpenID\Storage\AuthorizationCodeInterface to work when 'use_openid_connect' is true"); |
|
634 | + } |
|
635 | + $grantTypes['authorization_code'] = new OpenIDAuthorizationCodeGrantType($this->storages['authorization_code']); |
|
636 | + } else { |
|
637 | + $grantTypes['authorization_code'] = new AuthorizationCode($this->storages['authorization_code']); |
|
638 | + } |
|
639 | + } |
|
640 | + |
|
641 | + if (count($grantTypes) == 0) { |
|
642 | + throw new \LogicException("Unable to build default grant types - You must supply an array of grant_types in the constructor"); |
|
643 | + } |
|
644 | + |
|
645 | + return $grantTypes; |
|
646 | + } |
|
647 | + |
|
648 | + protected function getAccessTokenResponseType() |
|
649 | + { |
|
650 | + if (isset($this->responseTypes['token'])) { |
|
651 | + return $this->responseTypes['token']; |
|
652 | + } |
|
653 | + |
|
654 | + if ($this->config['use_jwt_access_tokens']) { |
|
655 | + return $this->createDefaultJwtAccessTokenResponseType(); |
|
656 | + } |
|
657 | + |
|
658 | + return $this->createDefaultAccessTokenResponseType(); |
|
659 | + } |
|
660 | + |
|
661 | + protected function getIdTokenResponseType() |
|
662 | + { |
|
663 | + if (isset($this->responseTypes['id_token'])) { |
|
664 | + return $this->responseTypes['id_token']; |
|
665 | + } |
|
666 | + |
|
667 | + return $this->createDefaultIdTokenResponseType(); |
|
668 | + } |
|
669 | + |
|
670 | + protected function getIdTokenTokenResponseType() |
|
671 | + { |
|
672 | + if (isset($this->responseTypes['id_token token'])) { |
|
673 | + return $this->responseTypes['id_token token']; |
|
674 | + } |
|
675 | + |
|
676 | + return $this->createDefaultIdTokenTokenResponseType(); |
|
677 | + } |
|
678 | + |
|
679 | + /** |
|
680 | + * For Resource Controller |
|
681 | + */ |
|
682 | + protected function createDefaultJwtAccessTokenStorage() |
|
683 | + { |
|
684 | + if (!isset($this->storages['public_key'])) { |
|
685 | + throw new \LogicException("You must supply a storage object implementing OAuth2\Storage\PublicKeyInterface to use crypto tokens"); |
|
686 | + } |
|
687 | + $tokenStorage = null; |
|
688 | + if (!empty($this->config['store_encrypted_token_string']) && isset($this->storages['access_token'])) { |
|
689 | + $tokenStorage = $this->storages['access_token']; |
|
690 | + } |
|
691 | + // wrap the access token storage as required. |
|
692 | + return new JwtAccessTokenStorage($this->storages['public_key'], $tokenStorage); |
|
693 | + } |
|
694 | + |
|
695 | + /** |
|
696 | + * For Authorize and Token Controllers |
|
697 | + */ |
|
698 | + protected function createDefaultJwtAccessTokenResponseType() |
|
699 | + { |
|
700 | + if (!isset($this->storages['public_key'])) { |
|
701 | + throw new \LogicException("You must supply a storage object implementing OAuth2\Storage\PublicKeyInterface to use crypto tokens"); |
|
702 | + } |
|
703 | + |
|
704 | + $tokenStorage = null; |
|
705 | + if (isset($this->storages['access_token'])) { |
|
706 | + $tokenStorage = $this->storages['access_token']; |
|
707 | + } |
|
708 | + |
|
709 | + $refreshStorage = null; |
|
710 | + if (isset($this->storages['refresh_token'])) { |
|
711 | + $refreshStorage = $this->storages['refresh_token']; |
|
712 | + } |
|
713 | + |
|
714 | + $config = array_intersect_key($this->config, array_flip(explode(' ', 'store_encrypted_token_string issuer access_lifetime refresh_token_lifetime'))); |
|
715 | + |
|
716 | + return new JwtAccessToken($this->storages['public_key'], $tokenStorage, $refreshStorage, $config); |
|
717 | + } |
|
718 | + |
|
719 | + protected function createDefaultAccessTokenResponseType() |
|
720 | + { |
|
721 | + if (!isset($this->storages['access_token'])) { |
|
722 | + throw new \LogicException("You must supply a response type implementing OAuth2\ResponseType\AccessTokenInterface, or a storage object implementing OAuth2\Storage\AccessTokenInterface to use the token server"); |
|
723 | + } |
|
724 | + |
|
725 | + $refreshStorage = null; |
|
726 | + if (isset($this->storages['refresh_token'])) { |
|
727 | + $refreshStorage = $this->storages['refresh_token']; |
|
728 | + } |
|
729 | + |
|
730 | + $config = array_intersect_key($this->config, array_flip(explode(' ', 'access_lifetime refresh_token_lifetime'))); |
|
731 | + $config['token_type'] = $this->tokenType ? $this->tokenType->getTokenType() : $this->getDefaultTokenType()->getTokenType(); |
|
732 | + |
|
733 | + return new AccessToken($this->storages['access_token'], $refreshStorage, $config); |
|
734 | + } |
|
735 | + |
|
736 | + protected function createDefaultIdTokenResponseType() |
|
737 | + { |
|
738 | + if (!isset($this->storages['user_claims'])) { |
|
739 | + throw new \LogicException("You must supply a storage object implementing OAuth2\OpenID\Storage\UserClaimsInterface to use openid connect"); |
|
740 | + } |
|
741 | + if (!isset($this->storages['public_key'])) { |
|
742 | + throw new \LogicException("You must supply a storage object implementing OAuth2\Storage\PublicKeyInterface to use openid connect"); |
|
743 | + } |
|
744 | + |
|
745 | + $config = array_intersect_key($this->config, array_flip(explode(' ', 'issuer id_lifetime'))); |
|
746 | + |
|
747 | + return new IdToken($this->storages['user_claims'], $this->storages['public_key'], $config); |
|
748 | + } |
|
749 | + |
|
750 | + protected function createDefaultIdTokenTokenResponseType() |
|
751 | + { |
|
752 | + return new IdTokenToken($this->getAccessTokenResponseType(), $this->getIdTokenResponseType()); |
|
753 | + } |
|
754 | + |
|
755 | + protected function validateOpenIdConnect() |
|
756 | + { |
|
757 | + $authCodeGrant = $this->getGrantType('authorization_code'); |
|
758 | + if (!empty($authCodeGrant) && !$authCodeGrant instanceof OpenIDAuthorizationCodeGrantType) { |
|
759 | + throw new \InvalidArgumentException('You have enabled OpenID Connect, but supplied a grant type that does not support it.'); |
|
760 | + } |
|
761 | + } |
|
762 | + |
|
763 | + protected function normalizeResponseType($name) |
|
764 | + { |
|
765 | + // for multiple-valued response types - make them alphabetical |
|
766 | + if (!empty($name) && false !== strpos($name, ' ')) { |
|
767 | + $types = explode(' ', $name); |
|
768 | + sort($types); |
|
769 | + $name = implode(' ', $types); |
|
770 | + } |
|
771 | + |
|
772 | + return $name; |
|
773 | + } |
|
774 | + |
|
775 | + public function getResponse() |
|
776 | + { |
|
777 | + return $this->response; |
|
778 | + } |
|
779 | + |
|
780 | + public function getStorages() |
|
781 | + { |
|
782 | + return $this->storages; |
|
783 | + } |
|
784 | + |
|
785 | + public function getStorage($name) |
|
786 | + { |
|
787 | + return isset($this->storages[$name]) ? $this->storages[$name] : null; |
|
788 | + } |
|
789 | + |
|
790 | + public function getGrantTypes() |
|
791 | + { |
|
792 | + return $this->grantTypes; |
|
793 | + } |
|
794 | + |
|
795 | + public function getGrantType($name) |
|
796 | + { |
|
797 | + return isset($this->grantTypes[$name]) ? $this->grantTypes[$name] : null; |
|
798 | + } |
|
799 | + |
|
800 | + public function getResponseTypes() |
|
801 | + { |
|
802 | + return $this->responseTypes; |
|
803 | + } |
|
804 | + |
|
805 | + public function getResponseType($name) |
|
806 | + { |
|
807 | + // for multiple-valued response types - make them alphabetical |
|
808 | + $name = $this->normalizeResponseType($name); |
|
809 | + |
|
810 | + return isset($this->responseTypes[$name]) ? $this->responseTypes[$name] : null; |
|
811 | + } |
|
812 | + |
|
813 | + public function getTokenType() |
|
814 | + { |
|
815 | + return $this->tokenType; |
|
816 | + } |
|
817 | + |
|
818 | + public function getClientAssertionType() |
|
819 | + { |
|
820 | + return $this->clientAssertionType; |
|
821 | + } |
|
822 | + |
|
823 | + public function setConfig($name, $value) |
|
824 | + { |
|
825 | + $this->config[$name] = $value; |
|
826 | + } |
|
827 | + |
|
828 | + public function getConfig($name, $default = null) |
|
829 | + { |
|
830 | + return isset($this->config[$name]) ? $this->config[$name] : $default; |
|
831 | + } |
|
832 | 832 | } |
@@ -10,47 +10,47 @@ |
||
10 | 10 | */ |
11 | 11 | class Autoloader |
12 | 12 | { |
13 | - private $dir; |
|
13 | + private $dir; |
|
14 | 14 | |
15 | - public function __construct($dir = null) |
|
16 | - { |
|
17 | - if (is_null($dir)) { |
|
18 | - $dir = dirname(__FILE__).'/..'; |
|
19 | - } |
|
20 | - $this->dir = $dir; |
|
21 | - } |
|
22 | - /** |
|
23 | - * Registers OAuth2\Autoloader as an SPL autoloader. |
|
24 | - */ |
|
25 | - public static function register($dir = null) |
|
26 | - { |
|
27 | - ini_set('unserialize_callback_func', 'spl_autoload_call'); |
|
28 | - spl_autoload_register(array(new self($dir), 'autoload')); |
|
29 | - } |
|
15 | + public function __construct($dir = null) |
|
16 | + { |
|
17 | + if (is_null($dir)) { |
|
18 | + $dir = dirname(__FILE__).'/..'; |
|
19 | + } |
|
20 | + $this->dir = $dir; |
|
21 | + } |
|
22 | + /** |
|
23 | + * Registers OAuth2\Autoloader as an SPL autoloader. |
|
24 | + */ |
|
25 | + public static function register($dir = null) |
|
26 | + { |
|
27 | + ini_set('unserialize_callback_func', 'spl_autoload_call'); |
|
28 | + spl_autoload_register(array(new self($dir), 'autoload')); |
|
29 | + } |
|
30 | 30 | |
31 | - /** |
|
32 | - * Handles autoloading of classes. |
|
33 | - * |
|
34 | - * @param string $class A class name. |
|
35 | - * |
|
36 | - * @return boolean Returns true if the class has been loaded |
|
37 | - */ |
|
38 | - public function autoload($class) |
|
39 | - { |
|
40 | - if (0 !== strpos($class, 'OAuth2')) { |
|
41 | - return; |
|
42 | - } |
|
31 | + /** |
|
32 | + * Handles autoloading of classes. |
|
33 | + * |
|
34 | + * @param string $class A class name. |
|
35 | + * |
|
36 | + * @return boolean Returns true if the class has been loaded |
|
37 | + */ |
|
38 | + public function autoload($class) |
|
39 | + { |
|
40 | + if (0 !== strpos($class, 'OAuth2')) { |
|
41 | + return; |
|
42 | + } |
|
43 | 43 | |
44 | - $class = str_replace('\\', '/', $class); |
|
44 | + $class = str_replace('\\', '/', $class); |
|
45 | 45 | |
46 | - if (strpos($class, 'OAuth2') === 0) |
|
47 | - { |
|
48 | - $count = 1; |
|
49 | - $class = str_replace('OAuth2', 'oauth2', $class, $count); |
|
50 | - } |
|
46 | + if (strpos($class, 'OAuth2') === 0) |
|
47 | + { |
|
48 | + $count = 1; |
|
49 | + $class = str_replace('OAuth2', 'oauth2', $class, $count); |
|
50 | + } |
|
51 | 51 | |
52 | - if (file_exists($file = $this->dir . '/' . $class . '.php')) { |
|
53 | - require $file; |
|
54 | - } |
|
55 | - } |
|
52 | + if (file_exists($file = $this->dir . '/' . $class . '.php')) { |
|
53 | + require $file; |
|
54 | + } |
|
55 | + } |
|
56 | 56 | } |
@@ -13,71 +13,71 @@ |
||
13 | 13 | */ |
14 | 14 | class UserCredentials implements GrantTypeInterface |
15 | 15 | { |
16 | - private $userInfo; |
|
16 | + private $userInfo; |
|
17 | 17 | |
18 | - protected $storage; |
|
18 | + protected $storage; |
|
19 | 19 | |
20 | - /** |
|
21 | - * @param OAuth2\Storage\UserCredentialsInterface $storage REQUIRED Storage class for retrieving user credentials information |
|
22 | - */ |
|
23 | - public function __construct(UserCredentialsInterface $storage) |
|
24 | - { |
|
25 | - $this->storage = $storage; |
|
26 | - } |
|
20 | + /** |
|
21 | + * @param OAuth2\Storage\UserCredentialsInterface $storage REQUIRED Storage class for retrieving user credentials information |
|
22 | + */ |
|
23 | + public function __construct(UserCredentialsInterface $storage) |
|
24 | + { |
|
25 | + $this->storage = $storage; |
|
26 | + } |
|
27 | 27 | |
28 | - public function getQuerystringIdentifier() |
|
29 | - { |
|
30 | - return 'password'; |
|
31 | - } |
|
28 | + public function getQuerystringIdentifier() |
|
29 | + { |
|
30 | + return 'password'; |
|
31 | + } |
|
32 | 32 | |
33 | - public function validateRequest(RequestInterface $request, ResponseInterface $response) |
|
34 | - { |
|
35 | - if (!$request->request("password") || !$request->request("username")) { |
|
36 | - $response->setError(400, 'invalid_request', 'Missing parameters: "username" and "password" required'); |
|
33 | + public function validateRequest(RequestInterface $request, ResponseInterface $response) |
|
34 | + { |
|
35 | + if (!$request->request("password") || !$request->request("username")) { |
|
36 | + $response->setError(400, 'invalid_request', 'Missing parameters: "username" and "password" required'); |
|
37 | 37 | |
38 | - return null; |
|
39 | - } |
|
38 | + return null; |
|
39 | + } |
|
40 | 40 | |
41 | - if (!$this->storage->checkUserCredentials($request->request("username"), $request->request("password"))) { |
|
42 | - $response->setError(401, 'invalid_grant', 'Invalid username and password combination'); |
|
41 | + if (!$this->storage->checkUserCredentials($request->request("username"), $request->request("password"))) { |
|
42 | + $response->setError(401, 'invalid_grant', 'Invalid username and password combination'); |
|
43 | 43 | |
44 | - return null; |
|
45 | - } |
|
44 | + return null; |
|
45 | + } |
|
46 | 46 | |
47 | - $userInfo = $this->storage->getUserDetails($request->request("username")); |
|
47 | + $userInfo = $this->storage->getUserDetails($request->request("username")); |
|
48 | 48 | |
49 | - if (empty($userInfo)) { |
|
50 | - $response->setError(400, 'invalid_grant', 'Unable to retrieve user information'); |
|
49 | + if (empty($userInfo)) { |
|
50 | + $response->setError(400, 'invalid_grant', 'Unable to retrieve user information'); |
|
51 | 51 | |
52 | - return null; |
|
53 | - } |
|
52 | + return null; |
|
53 | + } |
|
54 | 54 | |
55 | - if (!isset($userInfo['user_id'])) { |
|
56 | - throw new \LogicException("you must set the user_id on the array returned by getUserDetails"); |
|
57 | - } |
|
55 | + if (!isset($userInfo['user_id'])) { |
|
56 | + throw new \LogicException("you must set the user_id on the array returned by getUserDetails"); |
|
57 | + } |
|
58 | 58 | |
59 | - $this->userInfo = $userInfo; |
|
59 | + $this->userInfo = $userInfo; |
|
60 | 60 | |
61 | - return true; |
|
62 | - } |
|
61 | + return true; |
|
62 | + } |
|
63 | 63 | |
64 | - public function getClientId() |
|
65 | - { |
|
66 | - return null; |
|
67 | - } |
|
64 | + public function getClientId() |
|
65 | + { |
|
66 | + return null; |
|
67 | + } |
|
68 | 68 | |
69 | - public function getUserId() |
|
70 | - { |
|
71 | - return $this->userInfo['user_id']; |
|
72 | - } |
|
69 | + public function getUserId() |
|
70 | + { |
|
71 | + return $this->userInfo['user_id']; |
|
72 | + } |
|
73 | 73 | |
74 | - public function getScope() |
|
75 | - { |
|
76 | - return isset($this->userInfo['scope']) ? $this->userInfo['scope'] : null; |
|
77 | - } |
|
74 | + public function getScope() |
|
75 | + { |
|
76 | + return isset($this->userInfo['scope']) ? $this->userInfo['scope'] : null; |
|
77 | + } |
|
78 | 78 | |
79 | - public function createAccessToken(AccessTokenInterface $accessToken, $client_id, $user_id, $scope) |
|
80 | - { |
|
81 | - return $accessToken->createAccessToken($client_id, $user_id, $scope); |
|
82 | - } |
|
79 | + public function createAccessToken(AccessTokenInterface $accessToken, $client_id, $user_id, $scope) |
|
80 | + { |
|
81 | + return $accessToken->createAccessToken($client_id, $user_id, $scope); |
|
82 | + } |
|
83 | 83 | } |
@@ -13,88 +13,88 @@ |
||
13 | 13 | */ |
14 | 14 | class AuthorizationCode implements GrantTypeInterface |
15 | 15 | { |
16 | - protected $storage; |
|
17 | - protected $authCode; |
|
18 | - |
|
19 | - /** |
|
20 | - * @param OAuth2\Storage\AuthorizationCodeInterface $storage REQUIRED Storage class for retrieving authorization code information |
|
21 | - */ |
|
22 | - public function __construct(AuthorizationCodeInterface $storage) |
|
23 | - { |
|
24 | - $this->storage = $storage; |
|
25 | - } |
|
26 | - |
|
27 | - public function getQuerystringIdentifier() |
|
28 | - { |
|
29 | - return 'authorization_code'; |
|
30 | - } |
|
31 | - |
|
32 | - public function validateRequest(RequestInterface $request, ResponseInterface $response) |
|
33 | - { |
|
34 | - if (!$request->request('code')) { |
|
35 | - $response->setError(400, 'invalid_request', 'Missing parameter: "code" is required'); |
|
36 | - |
|
37 | - return false; |
|
38 | - } |
|
39 | - |
|
40 | - $code = $request->request('code'); |
|
41 | - if (!$authCode = $this->storage->getAuthorizationCode($code)) { |
|
42 | - $response->setError(400, 'invalid_grant', 'Authorization code doesn\'t exist or is invalid for the client'); |
|
43 | - |
|
44 | - return false; |
|
45 | - } |
|
46 | - |
|
47 | - /* |
|
16 | + protected $storage; |
|
17 | + protected $authCode; |
|
18 | + |
|
19 | + /** |
|
20 | + * @param OAuth2\Storage\AuthorizationCodeInterface $storage REQUIRED Storage class for retrieving authorization code information |
|
21 | + */ |
|
22 | + public function __construct(AuthorizationCodeInterface $storage) |
|
23 | + { |
|
24 | + $this->storage = $storage; |
|
25 | + } |
|
26 | + |
|
27 | + public function getQuerystringIdentifier() |
|
28 | + { |
|
29 | + return 'authorization_code'; |
|
30 | + } |
|
31 | + |
|
32 | + public function validateRequest(RequestInterface $request, ResponseInterface $response) |
|
33 | + { |
|
34 | + if (!$request->request('code')) { |
|
35 | + $response->setError(400, 'invalid_request', 'Missing parameter: "code" is required'); |
|
36 | + |
|
37 | + return false; |
|
38 | + } |
|
39 | + |
|
40 | + $code = $request->request('code'); |
|
41 | + if (!$authCode = $this->storage->getAuthorizationCode($code)) { |
|
42 | + $response->setError(400, 'invalid_grant', 'Authorization code doesn\'t exist or is invalid for the client'); |
|
43 | + |
|
44 | + return false; |
|
45 | + } |
|
46 | + |
|
47 | + /* |
|
48 | 48 | * 4.1.3 - ensure that the "redirect_uri" parameter is present if the "redirect_uri" parameter was included in the initial authorization request |
49 | 49 | * @uri - http://tools.ietf.org/html/rfc6749#section-4.1.3 |
50 | 50 | */ |
51 | - if (isset($authCode['redirect_uri']) && $authCode['redirect_uri']) { |
|
52 | - if (!$request->request('redirect_uri') || urldecode($request->request('redirect_uri')) != $authCode['redirect_uri']) { |
|
53 | - $response->setError(400, 'redirect_uri_mismatch', "The redirect URI is missing or do not match", "#section-4.1.3"); |
|
51 | + if (isset($authCode['redirect_uri']) && $authCode['redirect_uri']) { |
|
52 | + if (!$request->request('redirect_uri') || urldecode($request->request('redirect_uri')) != $authCode['redirect_uri']) { |
|
53 | + $response->setError(400, 'redirect_uri_mismatch', "The redirect URI is missing or do not match", "#section-4.1.3"); |
|
54 | 54 | |
55 | - return false; |
|
56 | - } |
|
57 | - } |
|
55 | + return false; |
|
56 | + } |
|
57 | + } |
|
58 | 58 | |
59 | - if (!isset($authCode['expires'])) { |
|
60 | - throw new \Exception('Storage must return authcode with a value for "expires"'); |
|
61 | - } |
|
59 | + if (!isset($authCode['expires'])) { |
|
60 | + throw new \Exception('Storage must return authcode with a value for "expires"'); |
|
61 | + } |
|
62 | 62 | |
63 | - if ($authCode["expires"] < time()) { |
|
64 | - $response->setError(400, 'invalid_grant', "The authorization code has expired"); |
|
63 | + if ($authCode["expires"] < time()) { |
|
64 | + $response->setError(400, 'invalid_grant', "The authorization code has expired"); |
|
65 | 65 | |
66 | - return false; |
|
67 | - } |
|
66 | + return false; |
|
67 | + } |
|
68 | 68 | |
69 | - if (!isset($authCode['code'])) { |
|
70 | - $authCode['code'] = $code; // used to expire the code after the access token is granted |
|
71 | - } |
|
69 | + if (!isset($authCode['code'])) { |
|
70 | + $authCode['code'] = $code; // used to expire the code after the access token is granted |
|
71 | + } |
|
72 | 72 | |
73 | - $this->authCode = $authCode; |
|
73 | + $this->authCode = $authCode; |
|
74 | 74 | |
75 | - return true; |
|
76 | - } |
|
75 | + return true; |
|
76 | + } |
|
77 | 77 | |
78 | - public function getClientId() |
|
79 | - { |
|
80 | - return $this->authCode['client_id']; |
|
81 | - } |
|
78 | + public function getClientId() |
|
79 | + { |
|
80 | + return $this->authCode['client_id']; |
|
81 | + } |
|
82 | 82 | |
83 | - public function getScope() |
|
84 | - { |
|
85 | - return isset($this->authCode['scope']) ? $this->authCode['scope'] : null; |
|
86 | - } |
|
83 | + public function getScope() |
|
84 | + { |
|
85 | + return isset($this->authCode['scope']) ? $this->authCode['scope'] : null; |
|
86 | + } |
|
87 | 87 | |
88 | - public function getUserId() |
|
89 | - { |
|
90 | - return isset($this->authCode['user_id']) ? $this->authCode['user_id'] : null; |
|
91 | - } |
|
88 | + public function getUserId() |
|
89 | + { |
|
90 | + return isset($this->authCode['user_id']) ? $this->authCode['user_id'] : null; |
|
91 | + } |
|
92 | 92 | |
93 | - public function createAccessToken(AccessTokenInterface $accessToken, $client_id, $user_id, $scope) |
|
94 | - { |
|
95 | - $token = $accessToken->createAccessToken($client_id, $user_id, $scope); |
|
96 | - $this->storage->expireAuthorizationCode($this->authCode['code']); |
|
93 | + public function createAccessToken(AccessTokenInterface $accessToken, $client_id, $user_id, $scope) |
|
94 | + { |
|
95 | + $token = $accessToken->createAccessToken($client_id, $user_id, $scope); |
|
96 | + $this->storage->expireAuthorizationCode($this->authCode['code']); |
|
97 | 97 | |
98 | - return $token; |
|
99 | - } |
|
98 | + return $token; |
|
99 | + } |
|
100 | 100 | } |