Skip to content

Commit fe78475

Browse files
authored
Merge pull request #15 from cmu-sei/fixing-keycloak-bug
fixed keycloak redirect bug
2 parents 31743ae + f514c3a commit fe78475

File tree

2 files changed

+63
-19
lines changed

2 files changed

+63
-19
lines changed

classes/crucible.php

Lines changed: 62 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1306,6 +1306,9 @@ public function get_keycloak_groups() {
13061306
return 0;
13071307
}
13081308

1309+
// Convert /admin/{realm}/console → /admin/realms/{realm}
1310+
$url = preg_replace('#/admin/([^/]+)/console$#', '/realms/$1', rtrim($url, '/'));
1311+
13091312
$url .= "/protocol/openid-connect/token";
13101313

13111314
$issuerid = get_config('block_crucible', 'issuerid');
@@ -1351,25 +1354,44 @@ public function get_keycloak_groups() {
13511354
// Initialize cURL.
13521355
$ch = curl_init();
13531356

1354-
// Web request
1357+
// Set the headers with the Authorization token.
1358+
$headers = [
1359+
"Authorization: Bearer $accessToken",
1360+
];
1361+
13551362
$realmUrl = get_config('block_crucible', 'keycloakadminurl');
13561363
if (empty($realmUrl)) {
13571364
return 0;
13581365
}
13591366

1360-
$userid = $USER->idnumber;
1367+
$realmUrl = preg_replace('#/admin/([^/]+)/console$#', '/admin/realms/$1', rtrim($realmUrl, '/'));
1368+
1369+
$username = $USER->username;
1370+
1371+
// Build user search URL
1372+
$userSearchUrl = $realmUrl . '/users?username=' . urlencode($username);
13611373

1362-
$realmUrl = rtrim($realmUrl, '/');
1363-
if (strpos($realmUrl, '/admin/realms/') === false && strpos($realmUrl, '/realms/') !== false) {
1364-
$realmUrl = str_replace('/realms/', '/admin/realms/', $realmUrl);
1374+
// Prepare request
1375+
curl_setopt($ch, CURLOPT_URL, $userSearchUrl);
1376+
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
1377+
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
1378+
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "GET");
1379+
1380+
$response = curl_exec($ch);
1381+
curl_close($ch);
1382+
1383+
$userlist = json_decode($response, true);
1384+
1385+
// Defensive check
1386+
if (!is_array($userlist) || empty($userlist)) {
1387+
debugging("No users found in Keycloak matching username: $username", DEBUG_DEVELOPER);
1388+
return 0;
13651389
}
13661390

1367-
$groupUrl = $realmUrl . '/users/' . urlencode($userid) . '/groups';
1391+
// Get the Keycloak UUID
1392+
$keycloakUserid = $userlist[0]['id'];
13681393

1369-
// Set the headers with the Authorization token.
1370-
$headers = [
1371-
"Authorization: Bearer $accessToken",
1372-
];
1394+
$groupUrl = $realmUrl . '/users/' . urlencode($keycloakUserid) . '/groups';
13731395

13741396
// Set cURL options for a GET request.
13751397
curl_setopt($ch, CURLOPT_URL, $groupUrl);
@@ -1379,6 +1401,7 @@ public function get_keycloak_groups() {
13791401

13801402
// Execute the request and capture the response.
13811403
$response = curl_exec($ch);
1404+
13821405
curl_close($ch);
13831406

13841407
// Check for errors and close the session.
@@ -1424,6 +1447,8 @@ public function get_keycloak_roles() {
14241447
return 0;
14251448
}
14261449

1450+
$url = preg_replace('#/admin/([^/]+)/console$#', '/realms/$1', rtrim($url, '/'));
1451+
14271452
$url .= "/protocol/openid-connect/token";
14281453

14291454
$issuerid = get_config('block_crucible', 'issuerid');
@@ -1472,21 +1497,40 @@ public function get_keycloak_roles() {
14721497
return 0;
14731498
}
14741499

1475-
$userid = $USER->idnumber;
1500+
$realmUrl = preg_replace('#/admin/([^/]+)/console$#', '/admin/realms/$1', rtrim($realmUrl, '/'));
14761501

1477-
// Normalize and convert to admin API path
1478-
$realmUrl = rtrim($realmUrl, '/');
1479-
if (strpos($realmUrl, '/admin/realms/') === false && strpos($realmUrl, '/realms/') !== false) {
1480-
$realmUrl = str_replace('/realms/', '/admin/realms/', $realmUrl);
1481-
}
1482-
1483-
$roleUrl = $realmUrl . '/users/' . urlencode($userid) . '/role-mappings/realm';
1502+
$username = $USER->username;
14841503

14851504
// Set the headers with the Authorization token.
14861505
$headers = [
14871506
"Authorization: Bearer $accessToken",
14881507
];
14891508

1509+
// Build user search URL
1510+
$userSearchUrl = $realmUrl . '/users?username=' . urlencode($username);
1511+
1512+
// Prepare request
1513+
curl_setopt($ch, CURLOPT_URL, $userSearchUrl);
1514+
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
1515+
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
1516+
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "GET");
1517+
1518+
$response = curl_exec($ch);
1519+
curl_close($ch);
1520+
1521+
$userlist = json_decode($response, true);
1522+
1523+
// Defensive check
1524+
if (!is_array($userlist) || empty($userlist)) {
1525+
debugging("No users found in Keycloak matching username: $username", DEBUG_DEVELOPER);
1526+
return 0;
1527+
}
1528+
1529+
// Get the Keycloak UUID
1530+
$keycloakUserid = $userlist[0]['id'];
1531+
1532+
$roleUrl = $realmUrl . '/users/' . urlencode($keycloakUserid) . '/role-mappings/realm';
1533+
14901534
// Set cURL options for a GET request.
14911535
curl_setopt($ch, CURLOPT_URL, $roleUrl);
14921536
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);

version.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@
4242

4343
defined('MOODLE_INTERNAL') || die;
4444

45-
$plugin->version = 2025052000;
45+
$plugin->version = 2025052101;
4646
$plugin->requires = 2021051100;
4747
$plugin->component = 'block_crucible';
4848
$plugin->maturity = MATURITY_ALPHA;

0 commit comments

Comments
 (0)