Skip to content

Commit d64485f

Browse files
committed
Handle url fragment # in url
1 parent 26fd906 commit d64485f

File tree

2 files changed

+46
-9
lines changed

2 files changed

+46
-9
lines changed

tests/www/LoginIntegrationTest.php

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -158,7 +158,7 @@ public function testValidServiceUrl()
158158
* @dataProvider buggyClientProvider
159159
* @return void
160160
*/
161-
public function testBuggyClientBadUrlEncodingWorkAround($service_url)
161+
public function testBuggyClientBadUrlEncodingWorkAround($service_url, $expectedStartsWith, $expectedEndsWith)
162162
{
163163
$this->authenticate();
164164

@@ -171,20 +171,34 @@ public function testBuggyClientBadUrlEncodingWorkAround($service_url)
171171
CURLOPT_COOKIEFILE => $this->cookies_file
172172
]
173173
);
174-
$this->assertEquals(302, $resp['code']);
174+
$this->assertEquals(302, $resp['code'], $resp['body']);
175175

176176
$this->assertStringStartsWith(
177-
$service_url . '?ticket=ST-',
177+
$expectedStartsWith,
178178
$resp['headers']['Location'],
179179
'Ticket should be part of the redirect.'
180180
);
181+
if (!empty($expectedEndsWith)) {
182+
$this->assertStringEndsWith(
183+
$expectedEndsWith,
184+
$resp['headers']['Location'],
185+
'url fragments happen after the query params'
186+
);
187+
}
181188
}
182189

183190
public function buggyClientProvider(): array
184191
{
192+
$urlWithQuery = 'https://buggy.edu/kc/portal.do?solo&ct=Search%20Prot&curl=https://kc.edu/kc/IRB.do?se=1875*&runSearch=1';
193+
$urlNoQuery = 'https://buggy.edu/kc';
194+
$urlMultiKeys = 'https://buggy.edu/kc?a=val1&a=val2';
185195
return [
186-
['https://buggy.edu/kc/portal.do?solo&ct=Search%20Prot&curl=https://kc.edu/kc/IRB.do?se=1875*&runSearch=1'],
187-
['https://buggy.edu/kc'],
196+
[$urlWithQuery, $urlWithQuery . '&ticket=ST-', ''],
197+
[$urlWithQuery . '#fragment', $urlWithQuery . '&ticket=ST-', '#fragment'],
198+
[$urlMultiKeys, $urlMultiKeys . '&ticket=ST-', ''],
199+
[$urlMultiKeys . '#fragment', $urlMultiKeys . '&ticket=ST-', '#fragment'],
200+
[$urlNoQuery, $urlNoQuery. '?ticket=ST-', ''],
201+
[$urlNoQuery . '#fragment', $urlNoQuery . '?ticket=ST-', '#fragment'],
188202
];
189203
}
190204

www/login.php

Lines changed: 27 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -211,10 +211,7 @@
211211
}
212212
} elseif ($redirect) {
213213
if ($casconfig->getBoolean('noReencode', false)) {
214-
// Some client encode query params wrong, and calling HTTP::addURLParameters
215-
// will reencode them resulting in service mismatches
216-
$extraParams = http_build_query($parameters);
217-
$redirectUrl = $_GET['service'] . (strpos('?', $_GET['service']) === false ? '?' : '&') . $extraParams;
214+
$redirectUrl = casAddURLParameters($_GET['service'], $parameters);
218215
HTTP::redirectTrustedURL($redirectUrl);
219216
} else {
220217
HTTP::redirectTrustedURL(HTTP::addURLParameters($_GET['service'], $parameters));
@@ -227,3 +224,29 @@
227224
HTTP::addURLParameters(Module::getModuleURL('casserver/loggedIn.php'), $parameters)
228225
);
229226
}
227+
228+
229+
/**
230+
* CAS wants to ensure that a service url provided in login matches exactly that provided in service validate.
231+
* This method avoids SSP's built in redirect which can change that url in certain ways, such as
232+
* * changing how a ' ' is encoded
233+
* * not correctly handling url fragments (e.g. #)
234+
* * not correctly handling query param keys occurring multiple times
235+
* * some buggy clients don't encode query params correctly
236+
* which results in either the wrong url being returned to the client, or a service mismatch
237+
* @param string $url The url to adjust
238+
* @param array $params The query parameters to add.
239+
* @return string The url to return
240+
*/
241+
function casAddURLParameters($url, $params)
242+
{
243+
$url_fragment = explode("#", $url);
244+
if (strpos($url_fragment[0], "?") === false) {
245+
$url_fragment[0] .= "?";
246+
} else {
247+
$url_fragment[0] .= "&";
248+
}
249+
$url_fragment[0] .= http_build_query($params);
250+
$url = implode("#", $url_fragment);
251+
return $url;
252+
}

0 commit comments

Comments
 (0)