@@ -104,10 +104,36 @@ public function send(Message $message) : void
104
104
public function receive (): Message
105
105
{
106
106
$ data = self ::parseQuery ();
107
- if (array_key_exists ('SAMLRequest ' , $ data )) {
108
- $ message = $ data ['SAMLRequest ' ];
109
- } elseif (array_key_exists ('SAMLResponse ' , $ data )) {
110
- $ message = $ data ['SAMLResponse ' ];
107
+ $ signedQuery = $ data ['SignedQuery ' ];
108
+
109
+ /**
110
+ * Get the SAMLRequest/SAMLResponse from the exact same signed data that will be verified later in
111
+ * validateSignature into $res using the actual SignedQuery
112
+ */
113
+ $ res = [];
114
+ foreach (explode ('& ' , $ signedQuery ) as $ e ) {
115
+ $ tmp = explode ('= ' , $ e , 2 );
116
+ $ name = $ tmp [0 ];
117
+ if (count ($ tmp ) === 2 ) {
118
+ $ value = $ tmp [1 ];
119
+ } else {
120
+ /* No value for this parameter. */
121
+ $ value = '' ;
122
+ }
123
+ $ name = urldecode ($ name );
124
+ $ res [$ name ] = urldecode ($ value );
125
+ }
126
+
127
+ /**
128
+ * Put the SAMLRequest/SAMLResponse from the actual query string into $message,
129
+ * and assert that the result from parseQuery() in $data and the parsing of the SignedQuery in $res agree
130
+ */
131
+ if (array_key_exists ('SAMLRequest ' , $ res )) {
132
+ Assert::same ($ res ['SAMLRequest ' ], $ data ['SAMLRequest ' ], 'Parse failure. ' );
133
+ $ message = $ res ['SAMLRequest ' ];
134
+ } elseif (array_key_exists ('SAMLResponse ' , $ res )) {
135
+ Assert::same ($ res ['SAMLResponse ' ], $ data ['SAMLResponse ' ], 'Parse failure. ' );
136
+ $ message = $ res ['SAMLResponse ' ];
111
137
} else {
112
138
throw new \Exception ('Missing SAMLRequest or SAMLResponse parameter. ' );
113
139
}
@@ -157,7 +183,7 @@ public function receive(): Message
157
183
$ signData = [
158
184
'Signature ' => $ data ['Signature ' ],
159
185
'SigAlg ' => $ data ['SigAlg ' ],
160
- 'Query ' => $ data [ ' SignedQuery ' ] ,
186
+ 'Query ' => $ signedQuery ,
161
187
];
162
188
163
189
$ message ->addValidator ([get_class ($ this ), 'validateSignature ' ], $ signData );
@@ -196,6 +222,10 @@ private static function parseQuery() : array
196
222
$ value = '' ;
197
223
}
198
224
$ name = urldecode ($ name );
225
+ // Prevent keys from being set more than once
226
+ if (array_key_exists ($ name , $ data )) {
227
+ throw new \Exception ('Duplicate parameter. ' );
228
+ }
199
229
$ data [$ name ] = urldecode ($ value );
200
230
201
231
switch ($ name ) {
@@ -211,6 +241,9 @@ private static function parseQuery() : array
211
241
break ;
212
242
}
213
243
}
244
+ if (array_key_exists ('SAMLRequest ' , $ data ) && array_key_exists ('SAMLResponse ' , $ data )) {
245
+ throw new \Exception ('Both SAMLRequest and SAMLResponse provided. ' );
246
+ }
214
247
215
248
$ data ['SignedQuery ' ] = $ sigQuery .$ relayState .$ sigAlg ;
216
249
0 commit comments