Skip to content

Commit 3c8953d

Browse files
committed
Handle url fragment # in url
1 parent 9823fec commit 3c8953d

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
@@ -234,7 +234,7 @@ public function testValidTicketNameOverride()
234234
* @dataProvider buggyClientProvider
235235
* @return void
236236
*/
237-
public function testBuggyClientBadUrlEncodingWorkAround($service_url)
237+
public function testBuggyClientBadUrlEncodingWorkAround($service_url, $expectedStartsWith, $expectedEndsWith)
238238
{
239239
$this->authenticate();
240240

@@ -247,20 +247,34 @@ public function testBuggyClientBadUrlEncodingWorkAround($service_url)
247247
CURLOPT_COOKIEFILE => $this->cookies_file
248248
]
249249
);
250-
$this->assertEquals(302, $resp['code']);
250+
$this->assertEquals(302, $resp['code'], $resp['body']);
251251

252252
$this->assertStringStartsWith(
253-
$service_url . '?ticket=ST-',
253+
$expectedStartsWith,
254254
$resp['headers']['Location'],
255255
'Ticket should be part of the redirect.'
256256
);
257+
if (!empty($expectedEndsWith)) {
258+
$this->assertStringEndsWith(
259+
$expectedEndsWith,
260+
$resp['headers']['Location'],
261+
'url fragments happen after the query params'
262+
);
263+
}
257264
}
258265

259266
public function buggyClientProvider(): array
260267
{
268+
$urlWithQuery = 'https://buggy.edu/kc/portal.do?solo&ct=Search%20Prot&curl=https://kc.edu/kc/IRB.do?se=1875*&runSearch=1';
269+
$urlNoQuery = 'https://buggy.edu/kc';
270+
$urlMultiKeys = 'https://buggy.edu/kc?a=val1&a=val2';
261271
return [
262-
['https://buggy.edu/kc/portal.do?solo&ct=Search%20Prot&curl=https://kc.edu/kc/IRB.do?se=1875*&runSearch=1'],
263-
['https://buggy.edu/kc'],
272+
[$urlWithQuery, $urlWithQuery . '&ticket=ST-', ''],
273+
[$urlWithQuery . '#fragment', $urlWithQuery . '&ticket=ST-', '#fragment'],
274+
[$urlMultiKeys, $urlMultiKeys . '&ticket=ST-', ''],
275+
[$urlMultiKeys . '#fragment', $urlMultiKeys . '&ticket=ST-', '#fragment'],
276+
[$urlNoQuery, $urlNoQuery. '?ticket=ST-', ''],
277+
[$urlNoQuery . '#fragment', $urlNoQuery . '?ticket=ST-', '#fragment'],
264278
];
265279
}
266280

www/login.php

Lines changed: 27 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -224,10 +224,7 @@
224224
}
225225
} elseif ($redirect) {
226226
if ($casconfig->getBoolean('noReencode', false)) {
227-
// Some client encode query params wrong, and calling HTTP::addURLParameters
228-
// will reencode them resulting in service mismatches
229-
$extraParams = http_build_query($parameters);
230-
$redirectUrl = $_GET['service'] . (strpos('?', $_GET['service']) === false ? '?' : '&') . $extraParams;
227+
$redirectUrl = casAddURLParameters($_GET['service'], $parameters);
231228
HTTP::redirectTrustedURL($redirectUrl);
232229
} else {
233230
HTTP::redirectTrustedURL(HTTP::addURLParameters($_GET['service'], $parameters));
@@ -240,3 +237,29 @@
240237
HTTP::addURLParameters(Module::getModuleURL('casserver/loggedIn.php'), $parameters)
241238
);
242239
}
240+
241+
242+
/**
243+
* CAS wants to ensure that a service url provided in login matches exactly that provided in service validate.
244+
* This method avoids SSP's built in redirect which can change that url in certain ways, such as
245+
* * changing how a ' ' is encoded
246+
* * not correctly handling url fragments (e.g. #)
247+
* * not correctly handling query param keys occurring multiple times
248+
* * some buggy clients don't encode query params correctly
249+
* which results in either the wrong url being returned to the client, or a service mismatch
250+
* @param string $url The url to adjust
251+
* @param array $params The query parameters to add.
252+
* @return string The url to return
253+
*/
254+
function casAddURLParameters($url, $params)
255+
{
256+
$url_fragment = explode("#", $url);
257+
if (strpos($url_fragment[0], "?") === false) {
258+
$url_fragment[0] .= "?";
259+
} else {
260+
$url_fragment[0] .= "&";
261+
}
262+
$url_fragment[0] .= http_build_query($params);
263+
$url = implode("#", $url_fragment);
264+
return $url;
265+
}

0 commit comments

Comments
 (0)