Skip to content

Commit e3fba5e

Browse files
authored
Merge pull request #27 from cirrusidentity/feature/alt-ticketname-support
Support alternate service and ticket param names
2 parents 0c0f2d4 + 19dfbea commit e3fba5e

4 files changed

Lines changed: 103 additions & 19 deletions

File tree

tests/config/module_casserver.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,9 @@
2727
'|https://override.example.com/|' => [
2828
'attrname' => 'uid',
2929
'attributes_to_transfer' => ['cn'],
30+
],
31+
'http://changeTicketParam' => [
32+
'ticketName' => 'myTicket',
3033
]
3134
],
3235

tests/www/LoginIntegrationTest.php

Lines changed: 76 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
namespace Simplesamlphp\Casserver;
44

55
use DOMDocument;
6+
use PHPUnit\Framework\TestCase;
67
use SimpleSAML\Test\BuiltInServer;
78

89
/**
@@ -13,11 +14,14 @@
1314
*
1415
* @package Simplesamlphp\Casserver
1516
*/
16-
class LoginIntegrationTest extends \PHPUnit\Framework\TestCase
17+
class LoginIntegrationTest extends TestCase
1718
{
1819
/** @var string $LINK_URL */
1920
private static $LINK_URL = '/module.php/casserver/login.php';
2021

22+
/** @var string $VALIDATE_URL */
23+
private static $VALIDATE_URL = '/module.php/casserver/serviceValidate.php';
24+
2125
/**
2226
* @var string $SAMLVALIDATE_URL
2327
*/
@@ -129,10 +133,13 @@ public function testWrongServiceUrl()
129133

130134

131135
/**
132-
* test a valid service URL
136+
* Test a valid service URL
137+
* @dataProvider validServiceUrlProvider
138+
* @param string $serviceParam The name of the query parameter to use for the service url
139+
* @param string $ticketParam The name of the query parameter that will contain the ticket
133140
* @return void
134141
*/
135-
public function testValidServiceUrl()
142+
public function testValidServiceUrl(string $serviceParam, string $ticketParam)
136143
{
137144
$service_url = 'http://host1.domain:1234/path1';
138145

@@ -141,7 +148,7 @@ public function testValidServiceUrl()
141148
/** @var array $resp */
142149
$resp = $this->server->get(
143150
self::$LINK_URL,
144-
['service' => $service_url],
151+
[$serviceParam => $service_url],
145152
[
146153
CURLOPT_COOKIEJAR => $this->cookies_file,
147154
CURLOPT_COOKIEFILE => $this->cookies_file
@@ -150,7 +157,71 @@ public function testValidServiceUrl()
150157
$this->assertEquals(302, $resp['code']);
151158

152159
$this->assertStringStartsWith(
153-
$service_url . '?ticket=ST-',
160+
$service_url . '?' . $ticketParam . '=ST-',
161+
$resp['headers']['Location'],
162+
'Ticket should be part of the redirect.'
163+
);
164+
165+
// Config ticket can be validated
166+
$matches = [];
167+
$this->assertEquals(1, preg_match("@$ticketParam=(.*)@", $resp['headers']['Location'], $matches));
168+
$ticket = $matches[1];
169+
$resp = $this->server->get(
170+
self::$VALIDATE_URL,
171+
[
172+
$serviceParam => $service_url,
173+
'ticket' => $ticket,
174+
],
175+
[
176+
CURLOPT_COOKIEJAR => $this->cookies_file,
177+
CURLOPT_COOKIEFILE => $this->cookies_file
178+
]
179+
);
180+
$expectedResponse = '<?xml version="1.0"?>
181+
<cas:serviceResponse xmlns:cas="http://www.yale.edu/tp/cas">
182+
<cas:authenticationSuccess>
183+
<cas:user>testuser@example.com</cas:user>
184+
<cas:attributes>
185+
<cas:eduPersonPrincipalName>testuser@example.com</cas:eduPersonPrincipalName>
186+
<cas:base64Attributes>false</cas:base64Attributes>
187+
</cas:attributes>
188+
</cas:authenticationSuccess>
189+
</cas:serviceResponse>';
190+
$this->assertEquals(200, $resp['code']);
191+
$this->assertEquals($expectedResponse, $resp['body']);
192+
}
193+
194+
public function validServiceUrlProvider(): array
195+
{
196+
return [
197+
['service', 'ticket'],
198+
['TARGET', 'SAMLart']
199+
];
200+
}
201+
202+
/**
203+
* Test changing the ticket name
204+
* @return void
205+
*/
206+
public function testValidTicketNameOverride()
207+
{
208+
$service_url = 'http://changeTicketParam/abc';
209+
210+
$this->authenticate();
211+
212+
/** @var array $resp */
213+
$resp = $this->server->get(
214+
self::$LINK_URL,
215+
['TARGET' => $service_url],
216+
[
217+
CURLOPT_COOKIEJAR => $this->cookies_file,
218+
CURLOPT_COOKIEFILE => $this->cookies_file
219+
]
220+
);
221+
$this->assertEquals(302, $resp['code']);
222+
223+
$this->assertStringStartsWith(
224+
$service_url . '?myTicket=ST-',
154225
$resp['headers']['Location'],
155226
'Ticket should be part of the redirect.'
156227
);

www/login.php

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -50,14 +50,16 @@
5050
$casconfig = Configuration::getConfig('module_casserver.php');
5151
$serviceValidator = new ServiceValidator($casconfig);
5252

53-
if (isset($_GET['service'])) {
54-
$serviceCasConfig = $serviceValidator->checkServiceURL(sanitize($_GET['service']));
53+
$serviceUrl = $_GET['service'] ?? $_GET['TARGET'] ?? null;
54+
55+
if (isset($serviceUrl)) {
56+
$serviceCasConfig = $serviceValidator->checkServiceURL(sanitize($serviceUrl));
5557
if (isset($serviceCasConfig)) {
5658
// Override the cas configuration to use for this service
5759
$casconfig = $serviceCasConfig;
5860
} else {
5961
$message = 'Service parameter provided to CAS server is not listed as a legal service: [service] = ' .
60-
var_export($_GET['service'], true);
62+
var_export($serviceUrl, true);
6163
Logger::debug('casserver:' . $message);
6264

6365
throw new \Exception($message);
@@ -113,6 +115,10 @@
113115
$query['service'] = $_REQUEST['service'];
114116
}
115117

118+
if (isset($_REQUEST['TARGET'])) {
119+
$query['TARGET'] = $_REQUEST['TARGET'];
120+
}
121+
116122
if (isset($_REQUEST['method'])) {
117123
$query['method'] = $_REQUEST['method'];
118124
}
@@ -174,12 +180,15 @@
174180
}
175181
}
176182

177-
if (isset($_GET['service'])) {
183+
if (isset($serviceUrl)) {
184+
$defaultTicketName = isset($_GET['service']) ? 'ticket' : 'SAMLart';
185+
$ticketName = $casconfig->getValue('ticketName', $defaultTicketName);
186+
178187
$attributeExtractor = new AttributeExtractor();
179188
$mappedAttributes = $attributeExtractor->extractUserAndAttributes($as->getAttributes(), $casconfig);
180189

181190
$serviceTicket = $ticketFactory->createServiceTicket([
182-
'service' => $_GET['service'],
191+
'service' => $serviceUrl,
183192
'forceAuthn' => $forceAuthn,
184193
'userName' => $mappedAttributes['user'],
185194
'attributes' => $mappedAttributes['attributes'],
@@ -189,7 +198,7 @@
189198

190199
$ticketStore->addTicket($serviceTicket);
191200

192-
$parameters['ticket'] = $serviceTicket['id'];
201+
$parameters[$ticketName] = $serviceTicket['id'];
193202

194203
$validDebugModes = ['true', 'samlValidate'];
195204
if (
@@ -205,7 +214,7 @@
205214
} else {
206215
$method = 'serviceValidate';
207216
// Fake some options for validateTicket
208-
$_GET['ticket'] = $serviceTicket['id'];
217+
$_GET[$ticketName] = $serviceTicket['id'];
209218
// We want to capture the output from echo used in validateTicket
210219
ob_start();
211220
require_once 'utility/validateTicket.php';
@@ -214,9 +223,9 @@
214223
echo '<pre>' . htmlspecialchars($casResponse) . '</pre>';
215224
}
216225
} elseif ($redirect) {
217-
HTTP::redirectTrustedURL(HTTP::addURLParameters($_GET['service'], $parameters));
226+
HTTP::redirectTrustedURL(HTTP::addURLParameters($serviceUrl, $parameters));
218227
} else {
219-
HTTP::submitPOSTData($_GET['service'], $parameters);
228+
HTTP::submitPOSTData($serviceUrl, $parameters);
220229
}
221230
} else {
222231
HTTP::redirectTrustedURL(

www/utility/validateTicket.php

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -41,8 +41,9 @@
4141
/** @var Cas20 $protocol */
4242
/** @psalm-suppress InvalidStringClass */
4343
$protocol = new $protocolClass($casconfig);
44+
$serviceUrl = $_GET['service'] ?? $_GET['TARGET'] ?? null;
4445

45-
if (array_key_exists('service', $_GET) && array_key_exists('ticket', $_GET)) {
46+
if (isset($serviceUrl) && array_key_exists('ticket', $_GET)) {
4647
$forceAuthn = isset($_GET['renew']) && $_GET['renew'];
4748

4849
try {
@@ -73,7 +74,7 @@
7374

7475
if (
7576
!$ticketFactory->isExpired($serviceTicket) &&
76-
sanitize($serviceTicket['service']) == sanitize($_GET['service']) &&
77+
sanitize($serviceTicket['service']) == sanitize($serviceUrl) &&
7778
(!$forceAuthn || $serviceTicket['forceAuthn'])
7879
) {
7980
$protocol->setAttributes($attributes);
@@ -91,7 +92,7 @@
9192
'userName' => $serviceTicket['userName'],
9293
'attributes' => $attributes,
9394
'forceAuthn' => false,
94-
'proxies' => array_merge([$_GET['service']], $serviceTicket['proxies']),
95+
'proxies' => array_merge([$serviceUrl], $serviceTicket['proxies']),
9596
'sessionId' => $serviceTicket['sessionId']
9697
]);
9798
try {
@@ -116,10 +117,10 @@
116117

117118
echo $protocol->getValidateFailureResponse('INVALID_TICKET', $message);
118119
} else {
119-
if (sanitize($serviceTicket['service']) != sanitize($_GET['service'])) {
120+
if (sanitize($serviceTicket['service']) != sanitize($serviceUrl)) {
120121
$message = 'Mismatching service parameters: expected ' .
121122
var_export($serviceTicket['service'], true) .
122-
' but was: ' . var_export($_GET['service'], true);
123+
' but was: ' . var_export($serviceUrl, true);
123124

124125
\SimpleSAML\Logger::debug('casserver:' . $message);
125126

0 commit comments

Comments
 (0)