diff --git a/app/controllers/AccountController.php b/app/controllers/AccountController.php index c95e285af..4999aa2e2 100644 --- a/app/controllers/AccountController.php +++ b/app/controllers/AccountController.php @@ -147,6 +147,7 @@ public function loginSubmit() $authzToken->accessToken = $accessToken; $authzToken->claimsMap['gatewayID'] = Config::get('pga_config.airavata')['gateway-id']; $authzToken->claimsMap['userName'] = $username; + $authzToken->claimsMap['custosId'] = Config::get('pga_config.wsis')['oauth-client-key']; Session::put('authz-token',$authzToken); Session::put('oauth-refresh-code',$refreshToken); @@ -156,7 +157,7 @@ public function loginSubmit() // AIRAVATA-3086: get gateway groups and get the groups this user is a member of $gatewayGroups = Airavata::getGatewayGroups($authzToken); $groupMemberships = GroupManagerService::getAllGroupsUserBelongs( - $authzToken, $username . "@" . Config::get('pga_config.airavata')['gateway-id']); + $authzToken, $username); $get_group_id = function($group) { return $group->id; }; diff --git a/app/controllers/GatewayRequestUpdateController.php b/app/controllers/GatewayRequestUpdateController.php index f75019e69..cbedd0695 100644 --- a/app/controllers/GatewayRequestUpdateController.php +++ b/app/controllers/GatewayRequestUpdateController.php @@ -41,7 +41,7 @@ public function updateDetails(){ return Redirect::back()->withErrors($validator); } else { - $returnVal = AdminUtilities::user_update_gateway(Input::get("internal-gateway-id"), Input::all()); + $returnVal = AdminUtilities::user_update_gateway(Input::get("gateway-id"), Input::all()); if ($returnVal == 1) { $email = Config::get('pga_config.portal')['admin-emails']; diff --git a/app/libraries/AdminUtilities.php b/app/libraries/AdminUtilities.php index 3c11266e4..a043699af 100644 --- a/app/libraries/AdminUtilities.php +++ b/app/libraries/AdminUtilities.php @@ -39,7 +39,16 @@ public static function add_gateway($inputs) $gateway->requesterUsername = Session::get('username'); $gateway->gatewayApprovalStatus = GatewayApprovalStatus::APPROVED; + $logoutURI = $gateway->gatewayURL; + if(!(AdminUtilities::endsWith($logoutURI,"/"))) { + $logoutURI = $logoutURI."/"; + } + $redirectURI = $logoutURI."auth/callback*"; + $gateway->redirectURLs = array($logoutURI,$redirectURI); + $gateway->scope = "openid profile email org.cilogon.userinfo" ; + try { + TenantProfileService::addGateway(Session::get('authz-token'), $gateway); return 1; } @@ -74,8 +83,7 @@ public static function check_request( $inputs) try { TenantProfileService::addGateway(Session::get('authz-token'), $gateway); return 1; - } - catch (Exception $ex) { + } catch (Exception $ex) { return -1; } } @@ -105,6 +113,21 @@ public static function request_gateway( $inputs) $gateway->gatewayPublicAbstract = $inputs["public-project-description"]; $gateway->requesterUsername = Session::get('username'); + + $logoutURI = $gateway->gatewayURL; + if(!(AdminUtilities::endsWith($logoutURI,"/"))) { + $logoutURI = $logoutURI."/"; + } + $redirectURI = $logoutURI."auth/callback*"; + $gateway->redirectURLs = array($logoutURI,$redirectURI); + $gateway->scope = "openid profile email org.cilogon.userinfo" ; + + $logoutURI = $gateway->gatewayURL; + $redirectURI = $logoutURI."auth/callback*"; + $gateway->redirectURLs = array($logoutURI,$redirectURI); + $gateway->scope = "openid profile email org.cilogon.userinfo" ; + + return TenantProfileService::addGateway(Session::get('authz-token'), $gateway); } @@ -129,9 +152,19 @@ public static function user_update_gateway( $gatewayId, $gatewayData){ $gateway->gatewayURL = $gatewayData["gateway-url"]; $gateway->reviewProposalDescription = $gatewayData["project-details"]; $gateway->gatewayPublicAbstract = $gatewayData["public-project-description"]; + + $logoutURI = $gateway->gatewayURL; + if(!(AdminUtilities::endsWith($logoutURI,"/"))) { + $logoutURI = $logoutURI."/"; + } + $redirectURI = $logoutURI."auth/callback*"; + $gateway->redirectURLs = array($logoutURI,$redirectURI); + $gateway->scope = "openid profile email org.cilogon.userinfo" ; + + if( TenantProfileService::updateGateway( Session::get('authz-token'), $gateway) ){ return 1; - } + } else{ //Need to find a better way for this. // retun echo "Tenant Name is already in use"; @@ -166,6 +199,14 @@ public static function update_gateway( $gatewayId, $gatewayData){ return -1; } } + $logoutURI = $gateway->gatewayURL; + if(!(AdminUtilities::endsWith($logoutURI,"/"))) { + $logoutURI = $logoutURI."/"; + } + $redirectURI = $logoutURI."auth/callback*"; + $gateway->redirectURLs = array($logoutURI,$redirectURI); + $gateway->scope = "openid profile email org.cilogon.userinfo" ; + $gateway = IamAdminServices::setUpGateway( Session::get('authz-token'), $gateway); $gateway->gatewayApprovalStatus = GatewayApprovalStatus::CREATED; } @@ -177,6 +218,7 @@ public static function update_gateway( $gatewayId, $gatewayData){ $gateway->gatewayAdminEmail = $gatewayData["gatewayAdminEmail"]; $gateway->identityServerUserName = $gatewayData["identityServerUserName"]; if (!empty($gatewayData["gatewayAdminPassword"])) { + $token = AdminUtilities::create_pwd_token([ "username" => $gatewayData["identityServerUserName"], "password" => $gatewayData["gatewayAdminPassword"], @@ -187,6 +229,15 @@ public static function update_gateway( $gatewayId, $gatewayData){ $gateway->reviewProposalDescription = $gatewayData["reviewProposalDescription"]; $gateway->gatewayPublicAbstract = $gatewayData["gatewayPublicAbstract"]; $gateway->gatewayApprovalStatus = GatewayApprovalStatus::APPROVED; + + $logoutURI = $gateway->gatewayURL; + $logoutURI = $gateway->gatewayURL; + if(!(AdminUtilities::endsWith($logoutURI,"/"))) { + $logoutURI = $logoutURI."/"; + } + $redirectURI = $logoutURI."auth/callback*"; + $gateway->redirectURLs = array($logoutURI,$redirectURI); + $gateway->scope = "openid profile email org.cilogon.userinfo" ; } elseif( isset( $gatewayData["denyRequest"])){ $gateway->gatewayApprovalStatus = GatewayApprovalStatus::DENIED; @@ -209,6 +260,13 @@ public static function update_gateway( $gatewayId, $gatewayData){ $gateway->reviewProposalDescription = $gatewayData["reviewProposalDescription"]; $gateway->gatewayPublicAbstract = $gatewayData["gatewayPublicAbstract"]; $gateway->gatewayApprovalStatus = GatewayApprovalStatus::APPROVED; + $logoutURI = $gateway->gatewayURL; + if(!(AdminUtilities::endsWith($logoutURI,"/"))) { + $logoutURI = $logoutURI."/"; + } + $redirectURI = $logoutURI."auth/callback*"; + $gateway->redirectURLs = array($logoutURI,$redirectURI); + $gateway->scope = "openid profile email org.cilogon.userinfo" ; } elseif( isset( $gatewayData["deployGateway"])){ $gateway->gatewayApprovalStatus = GatewayApprovalStatus::DEPLOYED; @@ -217,6 +275,7 @@ public static function update_gateway( $gatewayId, $gatewayData){ $gateway->gatewayApprovalStatus = GatewayApprovalStatus::DEACTIVATED; } + if( TenantProfileService::updateGateway( Session::get('authz-token'), $gateway) ){ return 1; } @@ -321,6 +380,7 @@ public static function create_pwd_token($inputs){ $username = $inputs['username']; $password = $inputs['password']; $description = $inputs['description']; + return $newToken = Airavata::registerPwdCredential( Session::get('authz-token'), $username, $password, $description); @@ -402,4 +462,10 @@ public static function add_or_update_IDP($inputs) return true; } + + + public static function endsWith($haystack, $needle) { + return substr_compare($haystack, $needle, -strlen($needle)) === 0; + } + } diff --git a/app/libraries/Airavata/Model/Workspace/Types.php b/app/libraries/Airavata/Model/Workspace/Types.php index 8a2f3cb82..efd10d01d 100644 --- a/app/libraries/Airavata/Model/Workspace/Types.php +++ b/app/libraries/Airavata/Model/Workspace/Types.php @@ -708,6 +708,14 @@ class Gateway { * @var string */ public $requesterUsername = null; + /** + * @var string[] + */ + public $redirectURLs = null; + /** + * @var string + */ + public $scope = null; public function __construct($vals=null) { if (!isset(self::$_TSPEC)) { @@ -792,6 +800,18 @@ public function __construct($vals=null) { 'var' => 'requesterUsername', 'type' => TType::STRING, ), + 21 => array( + 'var' => 'redirectURLs', + 'type' => TType::LST, + 'etype' => TType::STRING, + 'elem' => array( + 'type' => TType::STRING, + ), + ), + 22 => array( + 'var' => 'scope', + 'type' => TType::STRING, + ), ); } if (is_array($vals)) { @@ -855,6 +875,12 @@ public function __construct($vals=null) { if (isset($vals['requesterUsername'])) { $this->requesterUsername = $vals['requesterUsername']; } + if (isset($vals['redirectURLs'])) { + $this->redirectURLs = $vals['redirectURLs']; + } + if (isset($vals['scope'])) { + $this->scope = $vals['scope']; + } } } @@ -1017,6 +1043,30 @@ public function read($input) $xfer += $input->skip($ftype); } break; + case 21: + if ($ftype == TType::LST) { + $this->redirectURLs = array(); + $_size14 = 0; + $_etype17 = 0; + $xfer += $input->readListBegin($_etype17, $_size14); + for ($_i18 = 0; $_i18 < $_size14; ++$_i18) + { + $elem19 = null; + $xfer += $input->readString($elem19); + $this->redirectURLs []= $elem19; + } + $xfer += $input->readListEnd(); + } else { + $xfer += $input->skip($ftype); + } + break; + case 22: + if ($ftype == TType::STRING) { + $xfer += $input->readString($this->scope); + } else { + $xfer += $input->skip($ftype); + } + break; default: $xfer += $input->skip($ftype); break; @@ -1130,6 +1180,28 @@ public function write($output) { $xfer += $output->writeString($this->requesterUsername); $xfer += $output->writeFieldEnd(); } + if ($this->redirectURLs !== null) { + if (!is_array($this->redirectURLs)) { + throw new TProtocolException('Bad type in structure.', TProtocolException::INVALID_DATA); + } + $xfer += $output->writeFieldBegin('redirectURLs', TType::LST, 21); + { + $output->writeListBegin(TType::STRING, count($this->redirectURLs)); + { + foreach ($this->redirectURLs as $iter20) + { + $xfer += $output->writeString($iter20); + } + } + $output->writeListEnd(); + } + $xfer += $output->writeFieldEnd(); + } + if ($this->scope !== null) { + $xfer += $output->writeFieldBegin('scope', TType::STRING, 22); + $xfer += $output->writeString($this->scope); + $xfer += $output->writeFieldEnd(); + } $xfer += $output->writeFieldStop(); $xfer += $output->writeStructEnd(); return $xfer; diff --git a/app/libraries/GrouperUtilities.php b/app/libraries/GrouperUtilities.php index a167a3d66..28961e2cb 100644 --- a/app/libraries/GrouperUtilities.php +++ b/app/libraries/GrouperUtilities.php @@ -19,12 +19,8 @@ public static function getAllGatewayUsers() */ public static function shareResourceWithUsers($resourceId, $userPermissionMap) { - $newUserPermissionsMap = []; - foreach($userPermissionMap as $key=> $value){ - $key = $key . "@" . Config::get('pga_config.airavata')['gateway-id']; - $newUserPermissionsMap[$key] = $value; - } - Airavata::shareResourceWithUsers(Session::get('authz-token'), $resourceId, $newUserPermissionsMap); + + Airavata::shareResourceWithUsers(Session::get('authz-token'), $resourceId, $userPermissionMap); } /** @@ -33,12 +29,8 @@ public static function shareResourceWithUsers($resourceId, $userPermissionMap) */ public static function revokeSharingOfResourceFromUsers($resourceId, $userPermissionMap) { - $newUserPermissionsMap = []; - foreach($userPermissionMap as $key=> $value){ - $key = $key . "@" . Config::get('pga_config.airavata')['gateway-id']; - $newUserPermissionsMap[$key] = $value; - } - Airavata::revokeSharingOfResourceFromUsers(Session::get('authz-token'), $resourceId, $newUserPermissionsMap); + + Airavata::revokeSharingOfResourceFromUsers(Session::get('authz-token'), $resourceId, $userPermissionMap); } /** @@ -65,7 +57,7 @@ public static function getAllAccessibleUsers($resourceId, $permissionType) * @param $group Airavata/Model/Group/GrouoModel */ public static function createGroup($group){ - $group->ownerId = $group->ownerId . "@" . Config::get('pga_config.airavata')['gateway-id']; + Airavata::createGroup(Session::get('authz-token'),$group); } @@ -74,7 +66,7 @@ public static function createGroup($group){ * @param $group Airavata/Model/Group/GrouoModel */ public static function updateGroup($group){ - $group->ownerId = $group->ownerId . "@" . Config::get('pga_config.airavata')['gateway-id']; + Airavata::updateGroup(Session::get('authz-token'),$group); } diff --git a/app/libraries/Keycloak/API/BaseKeycloakAPIEndpoint.php b/app/libraries/Keycloak/API/BaseKeycloakAPIEndpoint.php index 93e7f7de3..62dc56b98 100644 --- a/app/libraries/Keycloak/API/BaseKeycloakAPIEndpoint.php +++ b/app/libraries/Keycloak/API/BaseKeycloakAPIEndpoint.php @@ -13,17 +13,25 @@ class BaseKeycloakAPIEndpoint { protected $admin_password; protected $verify_peer; protected $cafile_path; + protected $client_id; + protected $client_secret; + protected $openid_discovery_endpoint_url; + protected $custos_credential_uri; - function __construct($base_endpoint_url, $admin_username, $admin_password, $verify_peer, $cafile_path) { + function __construct($openid_discovery_endpoint_url, $base_endpoint_url, $admin_username, $admin_password, $verify_peer, $cafile_path, $client_id, $client_secret, $custos_credential_uri) { $this->base_endpoint_url = $base_endpoint_url; $this->admin_username = $admin_username; $this->admin_password = $admin_password; $this->verify_peer = $verify_peer; $this->cafile_path = $cafile_path; + $this->client_id = $client_id; + $this->client_secret = $client_secret; + $this->openid_discovery_endpoint_url = $openid_discovery_endpoint_url; + $this->custos_credential_uri = $custos_credential_uri; } - protected function getAPIAccessToken($realm) { + protected function getAPIAccessToken() { - return KeycloakUtil::getAPIAccessToken($this->base_endpoint_url, $realm, $this->admin_username, $this->admin_password, $this->verify_peer, $this->cafile_path); + return KeycloakUtil::getAPIAccessToken($this->openid_discovery_endpoint_url, $this->custos_credential_uri, $this->admin_username, $this->admin_password, $this->verify_peer, $this->cafile_path, $this->client_id, $this->client_secret); } } diff --git a/app/libraries/Keycloak/API/RoleMapper.php b/app/libraries/Keycloak/API/RoleMapper.php index 9a44f50cc..39845f293 100644 --- a/app/libraries/Keycloak/API/RoleMapper.php +++ b/app/libraries/Keycloak/API/RoleMapper.php @@ -18,13 +18,16 @@ class RoleMapper extends BaseKeycloakAPIEndpoint { * * Returns Array of RoleRepresentations */ - public function getRealmRoleMappingsForUser($realm, $user_id){ + public function getRealmRoleMappingsForUser($user_id){ // curl -H "Authorization: bearer $access_token" https://149.165.156.62:8443/auth/admin/realms/airavata/users/2c9ad2c6-0212-4aef-a5fb-9df862578934/role-mappings/realm // get access token for admin API - $access_token = $this->getAPIAccessToken($realm); - $url = $this->base_endpoint_url . '/admin/realms/' . rawurlencode($realm) . '/users/' . rawurlencode($user_id) . '/role-mappings/realm'; + + $url = $this->base_endpoint_url . '/user-management/v1.0.0/user'; + $params = "?client_id=" . urlencode($this->client_id). "&user.username=".urlencode($user_id); + $url = $url.$params; + // Log::debug("getRealmRoleMappingsForUser url", array($url)); $r = curl_init($url); curl_setopt($r, CURLOPT_RETURNTRANSFER, 1); @@ -34,9 +37,8 @@ public function getRealmRoleMappingsForUser($realm, $user_id){ curl_setopt($r, CURLOPT_CAINFO, $this->cafile_path); } curl_setopt($r, CURLOPT_HTTPHEADER, array( - "Authorization: Bearer " . $access_token + "Authorization: Basic " . base64_encode($this->client_id . ":" . $this->client_secret), )); - $response = curl_exec($r); if ($response == false) { Log::error("Failed to retrieve realm role mappings for user"); @@ -44,7 +46,7 @@ public function getRealmRoleMappingsForUser($realm, $user_id){ } $result = json_decode($response); // Log::debug("getRealmRoleMappingsForUser result", array($result)); - return $result; + return $result->realm_roles; } /** @@ -54,9 +56,8 @@ public function getRealmRoleMappingsForUser($realm, $user_id){ public function addRealmRoleMappingsToUser($realm, $user_id, $role_representations) { // get access token for admin API - $access_token = $this->getAPIAccessToken($realm); - $url = $this->base_endpoint_url . '/admin/realms/' . rawurlencode($realm) . '/users/' . rawurlencode($user_id) . '/role-mappings/realm'; - // Log::debug("addRealmRoleMappingsToUser", array($url, $role_representations)); + $access_token = $this->getAPIAccessToken(); + $url = $this->base_endpoint_url . '/user-management/v1.0.0/users/roles'; $r = curl_init($url); curl_setopt($r, CURLOPT_RETURNTRANSFER, 1); curl_setopt($r, CURLOPT_ENCODING, 1); @@ -66,19 +67,38 @@ public function addRealmRoleMappingsToUser($realm, $user_id, $role_representatio } curl_setopt($r, CURLOPT_POST, true); - $data = json_encode($role_representations); - // Log::debug("addRealmRoleMappingsToUser data=$data"); + + $roles = []; + foreach ($role_representations as $role) { + $roles[] = $role->name; + } + + $usernames = []; + $usernames[] = $user_id; + $client_level = false; + + $json = array("roles"=> $roles, "usernames"=> $usernames, "client_level" => $client_level); + + + $data = json_encode($json); + Log::debug("addRealmRoleMappingsToUser data=$data"); curl_setopt($r, CURLOPT_HTTPHEADER, array( - "Authorization: Bearer " . $access_token, + "Authorization: Bearer " .$access_token, 'Content-Type: application/json', 'Content-Length: ' . strlen($data)) ); curl_setopt($r, CURLOPT_POSTFIELDS, $data); $response = curl_exec($r); - $info = curl_getinfo($r); - if ($info['http_code'] != 200 && $info['http_code'] != 204) { - throw new Exception("Failed to add realm role mapping to user"); + + if ($response == false) { + Log::error("Failed to add realm role mappings for user"); + die("curl_exec() failed. Error: " . curl_error($r)); + } + $result = json_decode($response); + if ($result->status == false) { + Log::error("Failed to add realm role mappings for user"); + die("curl_exec() failed. Error: " . curl_error($r)); } return; } @@ -90,8 +110,8 @@ public function addRealmRoleMappingsToUser($realm, $user_id, $role_representatio public function deleteRealmRoleMappingsToUser($realm, $user_id, $role_representations) { // get access token for admin API - $access_token = $this->getAPIAccessToken($realm); - $url = $this->base_endpoint_url . '/admin/realms/' . rawurlencode($realm) . '/users/' . rawurlencode($user_id) . '/role-mappings/realm'; + $access_token = $this->getAPIAccessToken(); + $url = $this->base_endpoint_url . '/user-management/v1.0.0/user/roles'; // Log::debug("deleteRealmRoleMappingsToUser", array($url, $role_representations)); $r = curl_init($url); curl_setopt($r, CURLOPT_RETURNTRANSFER, 1); @@ -103,19 +123,33 @@ public function deleteRealmRoleMappingsToUser($realm, $user_id, $role_representa curl_setopt($r, CURLOPT_CUSTOMREQUEST, "DELETE"); curl_setopt($r, CURLOPT_POST, true); - $data = json_encode($role_representations); - // Log::debug("deleteRealmRoleMappingsToUser data=$data"); + + $roles = []; + foreach ($role_representations as $role) { + $roles[] = $role->name; + } + + $json = array("roles"=> $roles, "username"=> $user_id); + + $data = json_encode($json); + Log::debug("deleteRealmRoleMappingsToUser data=$data"); curl_setopt($r, CURLOPT_HTTPHEADER, array( - "Authorization: Bearer " . $access_token, + "Authorization: Bearer " .$access_token, 'Content-Type: application/json', 'Content-Length: ' . strlen($data)) ); curl_setopt($r, CURLOPT_POSTFIELDS, $data); $response = curl_exec($r); - $info = curl_getinfo($r); - if ($info['http_code'] != 200 && $info['http_code'] != 204) { - throw new Exception("Failed to delete realm role mapping to user"); + + if ($response == false) { + Log::error("Failed to delete realm role mappings for user"); + die("curl_exec() failed. Error: " . curl_error($r)); + } + $result = json_decode($response); + if ($result->status == false) { + Log::error("Failed to delete realm role mappings for user"); + die("curl_exec() failed. Error: " . curl_error($r)); } return; } diff --git a/app/libraries/Keycloak/API/Roles.php b/app/libraries/Keycloak/API/Roles.php index 1972e741a..f6e28e466 100644 --- a/app/libraries/Keycloak/API/Roles.php +++ b/app/libraries/Keycloak/API/Roles.php @@ -17,8 +17,9 @@ class Roles extends BaseKeycloakAPIEndpoint { public function getRoles($realm){ // get access token for admin API - $access_token = $this->getAPIAccessToken($realm); - $r = curl_init($this->base_endpoint_url . '/admin/realms/' . rawurlencode($realm) . '/roles'); + $url = $this->base_endpoint_url . '/tenant-management/v1.0.0/roles'; + $url = $url; + $r = curl_init($url); curl_setopt($r, CURLOPT_RETURNTRANSFER, 1); curl_setopt($r, CURLOPT_ENCODING, 1); curl_setopt($r, CURLOPT_SSL_VERIFYPEER, $this->verify_peer); @@ -26,7 +27,7 @@ public function getRoles($realm){ curl_setopt($r, CURLOPT_CAINFO, $this->cafile_path); } curl_setopt($r, CURLOPT_HTTPHEADER, array( - "Authorization: Bearer " . $access_token + "Authorization: Basic " . base64_encode($this->client_id . ":" . $this->client_secret), )); $response = curl_exec($r); @@ -35,6 +36,6 @@ public function getRoles($realm){ } $result = json_decode($response); // Log::debug("getRealmRoleMappingsForUser result", array($result)); - return $result; + return $result->roles; } } diff --git a/app/libraries/Keycloak/API/Users.php b/app/libraries/Keycloak/API/Users.php index efbdf57b3..cc5fbee15 100644 --- a/app/libraries/Keycloak/API/Users.php +++ b/app/libraries/Keycloak/API/Users.php @@ -1,4 +1,5 @@ getAPIAccessToken($realm); - $url = $this->base_endpoint_url . '/admin/realms/' . rawurlencode($realm) . '/users'; + $url = $this->base_endpoint_url . '/user-management/v1.0.0/users'; + $params = "?client_id=" . urlencode($this->client_id) . "&offset=" . urlencode(0) . "&limit=" . urlencode(100); + if ($username) { - $url = $url . '?username=' . rawurlencode($username); + $params = $params . '&user.username=' . rawurlencode($username); } + $url = $url . $params; // Log::debug("getUsers url", array($url)); $r = curl_init($url); curl_setopt($r, CURLOPT_RETURNTRANSFER, 1); curl_setopt($r, CURLOPT_ENCODING, 1); curl_setopt($r, CURLOPT_SSL_VERIFYPEER, $this->verify_peer); - if($this->verify_peer && $this->cafile_path){ + if ($this->verify_peer && $this->cafile_path) { curl_setopt($r, CURLOPT_CAINFO, $this->cafile_path); } curl_setopt($r, CURLOPT_HTTPHEADER, array( - "Authorization: Bearer " . $access_token + "Authorization: Basic " . base64_encode($this->client_id . ":" . $this->client_secret), )); $response = curl_exec($r); @@ -42,10 +47,11 @@ public function getUsers($realm, $username = null){ } $result = json_decode($response); // Log::debug("getUsers result", array($result)); - return $result; + return $result->users; } - public function getUserByUsername($realm, $username){ + public function getUserByUsername($realm, $username) + { # getUsers returns all users that have a username containing $username # so we need to check the returned users for one that matches exactly @@ -65,21 +71,23 @@ public function getUserByUsername($realm, $username){ * last names, and email address * Returns Array of UserRepresentation */ - public function searchUsers($realm, $keyword){ + public function searchUsers($realm, $keyword) + { // get access token for admin API - $access_token = $this->getAPIAccessToken($realm); - $url = $this->base_endpoint_url . '/admin/realms/' . rawurlencode($realm) . '/users?search=' . rawurlencode($keyword); + $url = $this->base_endpoint_url . '/user-management/v1.0.0/users'; + $params = "?client_id=" . urlencode($this->client_id) . "&offset=" . urlencode(0) . "&limit=" . urlencode(100) . "&user.id=" . urlencode($keyword); // Log::debug("getUsers url", array($url)); + $url = $url . $params; $r = curl_init($url); curl_setopt($r, CURLOPT_RETURNTRANSFER, 1); curl_setopt($r, CURLOPT_ENCODING, 1); curl_setopt($r, CURLOPT_SSL_VERIFYPEER, $this->verify_peer); - if($this->verify_peer && $this->cafile_path){ + if ($this->verify_peer && $this->cafile_path) { curl_setopt($r, CURLOPT_CAINFO, $this->cafile_path); } curl_setopt($r, CURLOPT_HTTPHEADER, array( - "Authorization: Bearer " . $access_token + "Authorization: Basic " . base64_encode($this->client_id . ":" . $this->client_secret), )); $response = curl_exec($r); @@ -88,7 +96,7 @@ public function searchUsers($realm, $keyword){ } $result = json_decode($response); // Log::debug("getUsers result", array($result)); - return $result; + return $result->users; } /** @@ -96,21 +104,23 @@ public function searchUsers($realm, $keyword){ * GET /admin/realms/{realm}/users/{id} * Returns a UserRepresentation */ - public function getUser($realm, $user_id) { + public function getUser($realm, $user_id) + { // get access token for admin API - $access_token = $this->getAPIAccessToken($realm); - $url = $this->base_endpoint_url . '/admin/realms/' . rawurlencode($realm) . '/users/' . rawurlencode($user_id); + $url = $this->base_endpoint_url . '/user-management/v1.0.0/users'; + $params = "?client_id=" . urlencode($this->client_id) . "&offset=" . urlencode(0) . "&limit=" . urlencode(100) . "&user.username=" . urlencode($user_id); + $url = $url . $params; // Log::debug("getUser url", array($url)); $r = curl_init($url); curl_setopt($r, CURLOPT_RETURNTRANSFER, 1); curl_setopt($r, CURLOPT_ENCODING, 1); curl_setopt($r, CURLOPT_SSL_VERIFYPEER, $this->verify_peer); - if($this->verify_peer && $this->cafile_path){ + if ($this->verify_peer && $this->cafile_path) { curl_setopt($r, CURLOPT_CAINFO, $this->cafile_path); } curl_setopt($r, CURLOPT_HTTPHEADER, array( - "Authorization: Bearer " . $access_token + "Authorization: Basic " . base64_encode($this->client_id . ":" . $this->client_secret), )); $response = curl_exec($r); diff --git a/app/libraries/Keycloak/Keycloak.php b/app/libraries/Keycloak/Keycloak.php index 8f859755e..2aeff0184 100644 --- a/app/libraries/Keycloak/Keycloak.php +++ b/app/libraries/Keycloak/Keycloak.php @@ -2,19 +2,17 @@ namespace Keycloak; -use Keycloak\API\RoleMapper; -use Keycloak\API\Roles; -use Keycloak\API\Users; -use Keycloak\KeycloakUtil; - use CommonUtilities; - use Exception; -use Log; use Illuminate\Routing\UrlGenerator; use Illuminate\Support\Facades\Config; +use Keycloak\API\RoleMapper; +use Keycloak\API\Roles; +use Keycloak\API\Users; +use Log; -class Keycloak { +class Keycloak +{ private $realm; private $openid_connect_discovery_url; @@ -27,6 +25,7 @@ class Keycloak { private $admin_username; private $admin_password; private $gateway_id; + private $custos_credentials_uri; // API clients private $role_mapper; @@ -37,7 +36,8 @@ class Keycloak { * Constructor * */ - public function __construct($realm, $openid_connect_discovery_url, $client_id, $client_secret, $callback_url, $cafile_path, $verify_peer, $base_endpoint_url, $admin_username, $admin_password, $gateway_id) { + public function __construct($realm, $openid_connect_discovery_url, $client_id, $client_secret, $callback_url, $cafile_path, $verify_peer, $base_endpoint_url, $admin_username, $admin_password, $gateway_id, $custos_credentials_uri) + { $this->realm = $realm; $this->openid_connect_discovery_url = $openid_connect_discovery_url; @@ -50,10 +50,11 @@ public function __construct($realm, $openid_connect_discovery_url, $client_id, $ $this->admin_username = $admin_username; $this->admin_password = $admin_password; $this->gateway_id = $gateway_id; + $this->custos_credentials_uri = $custos_credentials_uri; - $this->role_mapper = new RoleMapper($base_endpoint_url, $admin_username, $admin_password, $verify_peer, $this->cafile_path); - $this->roles = new Roles($base_endpoint_url, $admin_username, $admin_password, $verify_peer, $this->cafile_path); - $this->users = new Users($base_endpoint_url, $admin_username, $admin_password, $verify_peer, $this->cafile_path); + $this->role_mapper = new RoleMapper($openid_connect_discovery_url, $base_endpoint_url, $admin_username, $admin_password, $verify_peer, $this->cafile_path, $this->client_id, $this->client_secret, $this->custos_credentials_uri); + $this->roles = new Roles($openid_connect_discovery_url, $base_endpoint_url, $admin_username, $admin_password, $verify_peer, $this->cafile_path, $this->client_id, $this->client_secret, $this->custos_credentials_uri); + $this->users = new Users($openid_connect_discovery_url, $base_endpoint_url, $admin_username, $admin_password, $verify_peer, $this->cafile_path, $this->client_id, $this->client_secret, $this->custos_credentials_uri); } /** @@ -64,9 +65,12 @@ public function __construct($realm, $openid_connect_discovery_url, $client_id, $ * @return boolean * @throws Exception */ - public function authenticate($username, $password){ + public function authenticate($username, $password) + { + + Log::info("Calling authenticate ", array($username)); + $config = KeycloakUtil::getOpenIDConnectDiscoveryConfiguration($this->openid_connect_discovery_url, $this->client_id, $this->client_secret); - $config = $this->getOpenIDConnectDiscoveryConfiguration(); $token_endpoint = $config->token_endpoint; // Init cUrl. @@ -75,17 +79,22 @@ public function authenticate($username, $password){ // Decode compressed responses. curl_setopt($r, CURLOPT_ENCODING, 1); curl_setopt($r, CURLOPT_SSL_VERIFYPEER, $this->verify_peer); - if($this->verify_peer && $this->cafile_path){ + if ($this->verify_peer && $this->cafile_path) { curl_setopt($r, CURLOPT_CAINFO, $this->cafile_path); } + $auth_credentials = KeycloakUtil::getAuthCredentials($this->custos_credentials_uri, $this->client_id, $this->client_secret); + + $iam_secret = $auth_credentials->iam_client_secret; + + // Add client ID and client secret to the headers. curl_setopt($r, CURLOPT_HTTPHEADER, array( - "Authorization: Basic " . base64_encode($this->client_id . ":" . $this->client_secret), + "Authorization: Basic " . base64_encode($this->client_id . ":" . $iam_secret), )); // Assemble POST parameters for the request. - $post_fields = "client_id=" . urlencode($this->client_id) . "&client_secret=" . urlencode($this->client_secret) . "&grant_type=password"; + $post_fields = "client_id=" . urlencode($this->client_id) . "&client_secret=" . urlencode($iam_secret) . "&grant_type=password"; $post_fields .= "&username=" . urlencode($username) . "&password=" . urlencode($password); // Obtain and return the access token from the response. @@ -99,13 +108,16 @@ public function authenticate($username, $password){ //Parse JSON return object. $result = json_decode($response); - // Log::debug("password grant type authenciation response", array($result)); + + Log::debug("password grant type authenciation response", array($result)); return $result; - } + } - public function getOAuthRequestCodeUrl($extra_params=null){ - $config = $this->getOpenIDConnectDiscoveryConfiguration(); + public function getOAuthRequestCodeUrl($extra_params = null) + { + Log::info("Calling getOAuthRequestCodeUrl ", array($extra_params)); + $config = KeycloakUtil::getOpenIDConnectDiscoveryConfiguration($this->openid_connect_discovery_url, $this->client_id, $this->client_secret); $authorization_endpoint = $config->authorization_endpoint; // TODO: add state variable to request and put into session @@ -118,9 +130,11 @@ public function getOAuthRequestCodeUrl($extra_params=null){ return $url; } - public function getOAuthToken($code){ + public function getOAuthToken($code) + { - $config = $this->getOpenIDConnectDiscoveryConfiguration(); + + $config = KeycloakUtil::getOpenIDConnectDiscoveryConfiguration($this->openid_connect_discovery_url, $this->client_id, $this->client_secret); $token_endpoint = $config->token_endpoint; // Init cUrl. @@ -129,13 +143,18 @@ public function getOAuthToken($code){ // Decode compressed responses. curl_setopt($r, CURLOPT_ENCODING, 1); curl_setopt($r, CURLOPT_SSL_VERIFYPEER, $this->verify_peer); - if($this->verify_peer && $this->cafile_path){ + if ($this->verify_peer && $this->cafile_path) { curl_setopt($r, CURLOPT_CAINFO, $this->cafile_path); } + $auth_credentials = KeycloakUtil::getAuthCredentials($this->custos_credentials_uri, $this->client_id, $this->client_secret); + + + $iam_secret = $auth_credentials->iam_client_secret; + // Add client ID and client secret to the headers. curl_setopt($r, CURLOPT_HTTPHEADER, array( - "Authorization: Basic " . base64_encode($this->client_id . ":" . $this->client_secret), + "Authorization: Basic " . base64_encode($this->client_id . ":" . $iam_secret), )); // Assemble POST parameters for the request. @@ -157,9 +176,10 @@ public function getOAuthToken($code){ return $result; } - public function getUserProfileFromOAuthToken($token){ + public function getUserProfileFromOAuthToken($token) + { - $config = $this->getOpenIDConnectDiscoveryConfiguration(); + $config = KeycloakUtil::getOpenIDConnectDiscoveryConfiguration($this->openid_connect_discovery_url, $this->client_id, $this->client_secret); $userinfo_endpoint = $config->userinfo_endpoint; $r = curl_init($userinfo_endpoint); @@ -167,7 +187,7 @@ public function getUserProfileFromOAuthToken($token){ // Decode compressed responses. curl_setopt($r, CURLOPT_ENCODING, 1); curl_setopt($r, CURLOPT_SSL_VERIFYPEER, $this->verify_peer); - if($this->verify_peer && $this->cafile_path){ + if ($this->verify_peer && $this->cafile_path) { curl_setopt($r, CURLOPT_CAINFO, $this->cafile_path); } curl_setopt($r, CURLOPT_HTTPHEADER, array( @@ -181,20 +201,19 @@ public function getUserProfileFromOAuthToken($token){ //Parse JSON return object. $userinfo = json_decode($response); - Log::debug("Keycloak userinfo", array($userinfo)); $username = $userinfo->preferred_username; $firstname = $userinfo->given_name; $lastname = $userinfo->family_name; $email = $userinfo->email; // get roles from Keycloak API - $role_mappings = $this->role_mapper->getRealmRoleMappingsForUser($this->realm, $userinfo->sub); + $role_mappings = $this->role_mapper->getRealmRoleMappingsForUser($username); $roles = []; foreach ($role_mappings as $role_mapping) { - $roles[] = $role_mapping->name; + $roles[] = $role_mapping; } $roles = CommonUtilities::filterAiravataRoles($roles); - return array('username'=>$username, 'firstname'=>$firstname, 'lastname'=>$lastname, 'email'=>$email, 'roles'=>$roles); + return array('username' => $username, 'firstname' => $firstname, 'lastname' => $lastname, 'email' => $email, 'roles' => $roles); } /** @@ -202,9 +221,9 @@ public function getUserProfileFromOAuthToken($token){ * @param $refreshToken * @return mixed */ - public function getRefreshedOAuthToken($refresh_token){ - - $config = $this->getOpenIDConnectDiscoveryConfiguration(); + public function getRefreshedOAuthToken($refresh_token) + { + $config = KeycloakUtil::getOpenIDConnectDiscoveryConfiguration($this->openid_connect_discovery_url, $this->client_id, $this->client_secret); $token_endpoint = $config->token_endpoint; // Init cUrl. @@ -213,13 +232,18 @@ public function getRefreshedOAuthToken($refresh_token){ // Decode compressed responses. curl_setopt($r, CURLOPT_ENCODING, 1); curl_setopt($r, CURLOPT_SSL_VERIFYPEER, $this->verify_peer); - if($this->verify_peer && $this->cafile_path){ + if ($this->verify_peer && $this->cafile_path) { curl_setopt($r, CURLOPT_CAINFO, $this->cafile_path); } + $auth_credentials = KeycloakUtil::getAuthCredentials($this->custos_credentials_uri, $this->client_id, $this->client_secret); + + + $iam_secret = $auth_credentials->iam_client_secret; + // Add client ID and client secret to the headers. curl_setopt($r, CURLOPT_HTTPHEADER, array( - "Authorization: Basic " . base64_encode($this->client_id . ":" . $this->client_secret), + "Authorization: Basic " . base64_encode($this->client_id . ":" . $iam_secret), )); // Assemble POST parameters for the request. @@ -244,8 +268,9 @@ public function getRefreshedOAuthToken($refresh_token){ /** * Function to get the OAuth logout url */ - public function getOAuthLogoutUrl($redirect_uri) { - $config = $this->getOpenIDConnectDiscoveryConfiguration(); + public function getOAuthLogoutUrl($redirect_uri) + { + $config = KeycloakUtil::getOpenIDConnectDiscoveryConfiguration($this->openid_connect_discovery_url, $this->client_id, $this->client_secret); $logout_endpoint = $config->end_session_endpoint; return $logout_endpoint . '?redirect_uri=' . rawurlencode($redirect_uri); } @@ -255,12 +280,13 @@ public function getOAuthLogoutUrl($redirect_uri) { * * @return Array of usernames */ - public function listUsers(){ + public function listUsers() + { $users = $this->users->getUsers($this->realm); $usernames = []; foreach ($users as $user) { Log::debug("user", array($user)); - array_push($usernames, (object)["firstName"=>$user->firstName,"lastName"=>$user->lastName,"email"=>$user->email,"userEnabled"=>$user->enabled,"userName"=>$user->username]); + array_push($usernames, (object)["firstName" => $user->first_name, "lastName" => $user->last_name, "email" => $user->email, "userEnabled" => ($user->state === "ACTIVE"), "userName" => $user->username]); } return $usernames; } @@ -272,11 +298,12 @@ public function listUsers(){ * @param $keyword * @return Array of usernames */ - public function searchUsers($phrase){ + public function searchUsers($phrase) + { $users = $this->users->searchUsers($this->realm, $phrase); $usernames = []; foreach ($users as $user) { - array_push($usernames, (object)["firstName"=>$user->firstName,"lastName"=>$user->lastName,"email"=>$user->email,"userEnabled"=>$user->enabled,"userName"=>$user->username]); + array_push($usernames, (object)["firstName" => $user->first_name, "lastName" => $user->last_name, "email" => $user->email, "userEnabled" => ($user->state === "ACTIVE"), "userName" => $user->username]); } return $usernames; } @@ -287,8 +314,10 @@ public function searchUsers($phrase){ * * @return roles list */ - public function getAllRoles(){ + public function getAllRoles() + { try { + $roles = $this->roles->getRoles($this->realm); $role_names = []; foreach ($roles as $role) { @@ -306,15 +335,16 @@ public function getAllRoles(){ * * @return array of role names */ - public function getUserRoles( $username ){ + public function getUserRoles($username) + { try { + // get userid from username - $user_id = $this->getUserId($username); // Get the user's realm roles, then convert to an array of just names - $roles = $this->role_mapper->getRealmRoleMappingsForUser($this->realm, $user_id); + $roles = $this->role_mapper->getRealmRoleMappingsForUser($username); $role_names = []; foreach ($roles as $role) { - $role_names[] = $role->name; + $role_names[] = $role; } return CommonUtilities::filterAiravataRoles($role_names); } catch (Exception $ex) { @@ -326,15 +356,16 @@ public function getUserRoles( $username ){ * Function to update role list of user * * @param $username - * @param $roles, an Array with two entries, "deleted" and "new", each of + * @param $roles , an Array with two entries, "deleted" and "new", each of * which has a value of roles to be removed or added respectively * @return void */ - public function updateUserRoles( $username, $roles){ + public function updateUserRoles($username, $roles) + { // Log::debug("updateUserRoles", array($user_id, $roles)); try { + // get userid from username - $user_id = $this->getUserId($username); // Get all of the roles into an array keyed by role name $all_roles = $this->roles->getRoles($this->realm); $roles_by_name = []; @@ -343,20 +374,20 @@ public function updateUserRoles( $username, $roles){ } // Process the role deletions - if(isset($roles["deleted"])){ - if(!is_array($roles["deleted"])) + if (isset($roles["deleted"])) { + if (!is_array($roles["deleted"])) $roles["deleted"] = array($roles["deleted"]); foreach ($roles["deleted"] as $role) { - $this->role_mapper->deleteRealmRoleMappingsToUser($this->realm, $user_id, array($roles_by_name[$role])); + $this->role_mapper->deleteRealmRoleMappingsToUser($this->realm, $username, array($roles_by_name[$role])); } } // Process the role additions - if(isset($roles["new"])){ - if(!is_array($roles["new"])) + if (isset($roles["new"])) { + if (!is_array($roles["new"])) $roles["new"] = array($roles["new"]); foreach ($roles["new"] as $role) { - $this->role_mapper->addRealmRoleMappingsToUser($this->realm, $user_id, array($roles_by_name[$role])); + $this->role_mapper->addRealmRoleMappingsToUser($this->realm, $username, array($roles_by_name[$role])); } } } catch (Exception $ex) { @@ -368,16 +399,18 @@ public function updateUserRoles( $username, $roles){ * Function to get the user profile of a user * @param $username */ - public function getUserProfile($username){ + public function getUserProfile($username) + { + $user = $this->users->getUserByUsername($this->realm, $username); - if($user != null){ + if ($user != null) { $result = []; $result["email"] = $user->email; - $result["firstname"] = $user->firstName; - $result["lastname"] = $user->lastName; - $result["userEnabled"] = $user->enabled; + $result["firstname"] = $user->first_name; + $result["lastname"] = $user->last_name; + $result["userEnabled"] = ($user->state === "ACTIVE"); return $result; - }else{ + } else { return []; } @@ -388,46 +421,55 @@ public function getUserProfile($username){ * @param $username * @return bool */ - public function usernameExists($username){ - try{ + public function usernameExists($username) + { + try { + $user = $this->users->getUserByUsername($this->realm, $username); return $user != null; - }catch (Exception $ex){ + } catch (Exception $ex) { // Username does not exists return false; } } // TODO: move this to IamAdminServices - public function isUpdatePasswordRequired($username) { + public function isUpdatePasswordRequired($username) + { + + try { - try{ $user = $this->users->getUserByUsername($this->realm, $username); if ($user != null) { return in_array("UPDATE_PASSWORD", $user->requiredActions); } else { return false; } - }catch (Exception $ex){ + } catch (Exception $ex) { // Username does not exists return false; } } - public function getAdminAuthzToken() { + public function getAdminAuthzToken() + { - $access_token = KeycloakUtil::getAPIAccessToken($this->base_endpoint_url, $this->realm, $this->admin_username, $this->admin_password, $this->verify_peer, $this->cafile_path); + $access_token = KeycloakUtil::getAPIAccessToken($this->openid_connect_discovery_url, $this->custos_credentials_uri, + $this->admin_username, $this->admin_password, $this->verify_peer, $this->cafile_path, + $this->client_id, $this->client_secret); $authzToken = new \Airavata\Model\Security\AuthzToken(); $authzToken->accessToken = $access_token; $authzToken->claimsMap['gatewayID'] = $this->gateway_id; $authzToken->claimsMap['userName'] = $this->admin_username; + $authzToken->claimsMap['custosId'] = $this->client_id; return $authzToken; } /** * Get the user's Keycloak user_id from their username */ - private function getUserId($username) { + private function getUserId($username) + { $user = $this->users->getUserByUsername($this->realm, $username); if ($user != null) { return $user->id; @@ -436,27 +478,6 @@ private function getUserId($username) { } } - private function getOpenIDConnectDiscoveryConfiguration() { - // TODO: cache the result of the request - $r = curl_init($this->openid_connect_discovery_url); - curl_setopt($r, CURLOPT_RETURNTRANSFER, 1); - // Decode compressed responses. - curl_setopt($r, CURLOPT_ENCODING, 1); - curl_setopt($r, CURLOPT_SSL_VERIFYPEER, $this->verify_peer); - if($this->verify_peer && $this->cafile_path){ - curl_setopt($r, CURLOPT_CAINFO, $this->cafile_path); - } - - $result = curl_exec($r); - if ($result == false) { - die("curl_exec() failed. Error: " . curl_error($r)); - } - - $json = json_decode($result); - - // Log::debug("openid connect discovery configuration", array($json)); - return $json; - } } diff --git a/app/libraries/Keycloak/KeycloakServiceProvider.php b/app/libraries/Keycloak/KeycloakServiceProvider.php index db64fb084..06694f347 100644 --- a/app/libraries/Keycloak/KeycloakServiceProvider.php +++ b/app/libraries/Keycloak/KeycloakServiceProvider.php @@ -46,7 +46,9 @@ public function register() $identityServerConfig['service-url'], $identityServerConfig['admin-username'], $identityServerConfig['admin-password'], - $airavataConfig['gateway-id'] + $airavataConfig['gateway-id'], + $identityServerConfig['custos-credentials-uri'] + ); }); diff --git a/app/libraries/Keycloak/KeycloakUtil.php b/app/libraries/Keycloak/KeycloakUtil.php index 41880cb54..361db9859 100644 --- a/app/libraries/Keycloak/KeycloakUtil.php +++ b/app/libraries/Keycloak/KeycloakUtil.php @@ -1,27 +1,32 @@ token_endpoint; - $r = curl_init($base_endpoint_url . '/realms/' . rawurlencode($realm) . '/protocol/openid-connect/token'); + $r = curl_init($token_endpoint); curl_setopt($r, CURLOPT_RETURNTRANSFER, 1); curl_setopt($r, CURLOPT_ENCODING, 1); curl_setopt($r, CURLOPT_SSL_VERIFYPEER, $verify_peer); - if($verify_peer && $cafile_path){ + if ($verify_peer && $cafile_path) { curl_setopt($r, CURLOPT_CAINFO, $cafile_path); } + $credentials = KeycloakUtil::getAuthCredentials($custos_credentials_uri, $client_id, $client_sec); + // Assemble POST parameters for the request. - $post_fields = "client_id=admin-cli&username=" . urlencode($admin_username) . "&password=" . urlencode($admin_password) . "&grant_type=password"; + $post_fields = "client_id=" . urlencode($client_id) . "&client_secret=" . urlencode($credentials->iam_client_secret) . "&username=" + . urlencode($admin_username) . "&password=" . urlencode($admin_password) . "&grant_type=password"; // Obtain and return the access token from the response. curl_setopt($r, CURLOPT_POST, true); @@ -34,7 +39,66 @@ public static function getAPIAccessToken($base_endpoint_url, $realm, $admin_user } $result = json_decode($response); - // Log::debug("API Access Token result", array($result)); + return $result->access_token; } + + public static function getOpenIDConnectDiscoveryConfiguration($openid_connect_discovery_url, $client_id, $client_secret) + { + + $post_files = "?client_id=" . urlencode($client_id); + $url = $openid_connect_discovery_url . $post_files; + + // TODO: cache the result of the request + $r = curl_init($url); + + curl_setopt($r, CURLOPT_HTTPHEADER, array( + "Authorization: Basic " . base64_encode($client_id . ":" . $client_secret), + )); + + + curl_setopt($r, CURLOPT_RETURNTRANSFER, 1); + // Decode compressed responses. + curl_setopt($r, CURLOPT_ENCODING, 1); + + $result = curl_exec($r); + if ($result == false) { + die("curl_exec() failed. Error: " . curl_error($r)); + } + + $json = json_decode($result); + + + // Log::debug("openid connect discovery configuration", array($json)); + return $json; + } + + public static function getAuthCredentials($custos_credentials_uri, $client_id, $client_secret) + { + + $post_files = "?client_id=" . urlencode($client_id); + $url = $custos_credentials_uri . $post_files; + + // TODO: cache the result of the request + $r = curl_init($url); + + curl_setopt($r, CURLOPT_HTTPHEADER, array( + "Authorization: Basic " . base64_encode($client_id . ":" . $client_secret), + )); + + + curl_setopt($r, CURLOPT_RETURNTRANSFER, 1); + // Decode compressed responses. + curl_setopt($r, CURLOPT_ENCODING, 1); + + $result = curl_exec($r); + if ($result == false) { + die("curl_exec() failed. Error: " . curl_error($r)); + } + + $json = json_decode($result); + + // Log::debug("openid connect discovery configuration", array($json)); + return $json; + } }