Code Monkey home page Code Monkey logo

onelogin-php-sdk's Introduction

OneLogin PHP SDK

This SDK will let you execute all the API methods, version/1, described at https://developers.onelogin.com/api-docs/1/getting-started/dev-overview.

Installation

Hosting

Github

The toolkit is hosted on github. You can download it from:

Composer

The toolkit supports composer. You can find the onelogin/api package at https://packagist.org/packages/onelogin/api

In order to import the sdk into your current php project, execute

composer require onelogin/api

Dependencies

The SDK has the following dependencies:

  • PHP >5.6
  • guzzle

Getting started

You'll need a OneLogin account and a set of API credentials before you get started.

If you don't have an account you can sign up for a free developer account here.

client_id Required: A valid OneLogin API client_id
client_secret Required: A valid OneLogin API client_secret
region Optional: us or eu. Defaults to us
<?php

use \OneLogin\api\OneLoginClient;

$client = new OneLoginClient($clientId, $clientSecret, $region);

#Now you can make requests 
client.getUsers()

For all methods see PHPdoc of this SDK published at: https://onelogin.github.io/onelogin-php-sdk/index.html

Usage

Errors and exceptions

OneLogin's API can return 400, 401, 403 or 404 when there was any issue executing the action. When that happens, the methods of the SDK will include error and errorMessage in the OneLoginClient. Use the getError() and the getErrorDescription() to retrieve them.

In some scenarios there is an attribute not provided or invalid that causes the error on the execution of the API call, when that happens at the OneLoginClient there is available a getErrorAttribute() method that contains the name of the attribute that caused the issue. See the API documentation to verify when this data is provided by the API.

Authentication

By default methods call internally to getAccessToken if there is no valid accessToken. You can also get tokens etc directly if needed.

/* Get an AccessToken */
$token = $client->getAccessToken();

/* Refresh an AccessToken */
$token2 = $client->refreshToken();

/* Revoke an AccessToken */
$client->revokeToken();

Searchs

By default a search (getUsers, getEvents, getRoles, getGroups) will return a max of results determined by the client parameter maxResults (1000), but the search accept this parameter to get a different number of results. The max_results attribute of the client can be also overriden.

Available Methods

/* Get rate limits */
$rateLimit = $client->getRateLimit();

/* Get Custom Attributes */
$customGlobalAttributes = $client->getCustomAttributes();

/* Get Users with no query parameters */
$users = $client->getUsers();

/* Get Users with query parameters */
$queryParameters = array (
    "email" => "[email protected]"
);
$usersFiltered = $client->getUsers($queryParameters);

$queryParameters = array (
    "email" => "[email protected]"
);
$usersFiltered2 = $client->getUsers($queryParameters);

/* Get 10 Users with role_id 2 */
$queryParameters = array (
    "role_id" => 2
);
$usersFilteredByRoleId = $client->getUsers($queryParameters, 10);

/* Get User By ID */
$user = $client->getUser($usersFiltered[0]->id);
$userMFA = $client->getUser($usersFiltered2[0]->id);

/* Update User with specific id */
$user = $client->getUser($user->id);
$updateUserParams = $user->getUserParams();
$updateUserParams["firstname"] = "modified_firstname";
$user = $client->updateUser($user->id, $updateUserParams);

 /* Get Global Roles */
$roles = $client->getRoles();

/* Get Role */
$role = $client->getRole($roles[0]->getId());
$role2 = $client->getRole($roles[1]->getId());
       
/* Assign & Remove Roles On Users */
$newRoleIds = array(
       $role->getId(),
       $role2->getId()
);
$client->assignRoleToUser($user->id, $newRoleIds);
$user = $client->getUser($user->id);
array_pop($newRoleIds);
$client->removeRoleFromUser($user->id, $newRoleIds);
$user = $client->getUser($user->id);

/* Sets Password by ID Using Cleartext */
$password = "Aa765431-XxX";
$client->setPasswordUsingClearText($user->id, $password, $password);

/* Sets Password by ID Using Salt and SHA-256 */
$password = "Aa765432-YyY";
$salt = "11xxxx1";
$hashedSaltedPassword = hash('sha256', $salt . $password);
$client->setPasswordUsingHashSalt($userMFA->id, $hashedSaltedPassword, $hashedSaltedPassword, "salt+sha256", $salt);

/* Set Custom Attribute Value to User */
$customAttributes = array(
    $customGlobalAttributes[0] => "xxxx",
    $customGlobalAttributes[1] => "yyyy"
);
$client->setCustomAttributeToUser($user->id, $customAttributes);

/* Log Out User */
$client->logUserOut($user->id);

/* Lock User */
$client->lockUser($user->id, 1); // Lock the user 1 min

/* Get User apps */
$userApps = $client->getUserApps($user->id);

/* Get User Roles */
$userRolesIds = $client->getUserRoles($user->id);

/* Generate MFA Token */
$mfaToken = $client->generateMFAToken($user->id);

/* Get all Apps in a OneLogin account */
$apps = $client->getApps();

/* Create user */
$newUserParams = array(
    "email" => "[email protected]",
    "firstname" => "testcreate_1_fn",
    "lastname" => "testcreate_1_ln",
    "username" => "[email protected]"
);
$createdUser = $client->createUser($newUserParams);

/* Delete user */
$removed = $client->deleteUser($createdUser->id);

/* Get EventTypes */
$eventTypes = $client->getEventTypes();

/* Get Events */
$events = $client->getEvents();

/* Get Event */
$event = $client->getEvent($events[0]->id);
           
/* Create Event */
$eventParams = array(
    "event_type_id" => 000,
    "account_id" => 00000,
    "actor_system" => 00,
    "user_id" => 00000000,
    "user_name" => "test_event",
    "custom_message" => "test creating event :)"
);
$client->createEvent($eventParams);


/* Get Filtered Events */
$eventQueryParameters = array(
  "user_id" => 00000000
);
$events = $client->getEvents($eventQueryParameters);

/* Get Groups */
$groups = $client->getGroups();

/* Get Group */
$group = $client->getGroup($groups[0]->getId());

/* Get SAMLResponse directly */
$appId = "000000";
$samlEndpointResponse = $client->getSAMLAssertion("[email protected]", "Aa765431-XxX", $appId, "example-onelogin-subdomain");

/* Get SAMLResponse after MFA */
$samlEndpointResponse2 = $client->getSAMLAssertion("[email protected]", "Aa765432-YyY", $appId, "example-onelogin-subdomain");
$mfa = $samlEndpointResponse2->getMFA();
$otpToken = "000000";
$samlEndpointResponseAfterVerify = $client->getSAMLAssertionVerifying($appId, $mfa->getDevices()[0]->getID(), $mfa->getStateToken(), $otpToken, null);

/* Create Session Login Token */
$sessionLoginTokenParams = array(
    "username_or_email" => "[email protected]",
    "password" => "Aa765431-XxX",
    "subdomain"=> "example-onelogin-subdomain"
);
$sessionTokenData = $client->createSessionLoginToken($sessionLoginTokenParams);

/* Create Session Login Token MFA , after verify */
$sessionLoginTokenMFAParams = array(
    "username_or_email" => "[email protected]",
    "password" => "Aa765432-YyY",
    "subdomain" => "example-onelogin-subdomain"
);
$sessionTokenMFAData = $client->createSessionLoginToken($sessionLoginTokenMFAParams);
$otpCode = "645645"; // We may take that value from OTP device
$sessionTokenData2 = $client->getSessionTokenVerified($sessionTokenMFAData->devices[0]->getID(), $sessionTokenMFAData->stateToken, $otpCode);

$userId = 00000000;
# Get Available Authentication Factors
$authFactors = $client->getFactors($userId);

# Enroll an Authentication Factor
$enrollFactor = $client->enrollFactor($userId, $authFactors[0]->id, 'My Device', '+14156456830');

# Get Enrolled Authentication Factors
$otpDevices = $client->getEnrolledFactors($userId);
 
# Activate an Authentication Factor
$deviceId = 0000000;
$enrollmentResponse = $client->activateFactor($userId, $deviceId);

# Verify an Authentication Factor
$otpToken="XXXXXXXXXX";
$result = $client->verifyFactor($userId, $deviceId, $otpToken);

# Remove Factor
$result = $client->removeFactor($userId, $deviceId);

/* Generate Invite Link */
$urlLink = $client->generateInviteLink("[email protected]");

/* Send Invite Link */
$sent = $client->sendInviteLink("[email protected]");

/* Get Apps to Embed for a User */
$embedToken = "30e256c101cd0d2e731de1ec222e93c4be8a1578";
$apps = $client->getEmbedApps($embedToken, "[email protected]");

/* Get Privileges */
$privileges = $client->getPrivileges();

/* Create Privilege */
$name = "privilege_example";
$version = "2018-05-18";

$statement1 = new Statement(
    "Allow",
    [
        "users:List",
        "users:Get",
    ],
    ["*"]
);

$statement2 = new Statement(
    "Allow",
    [
        "apps:List",
        "apps:Get",
    ],
    ["*"]
);

$statements = array(
    $statement1,
    $statement2
);

$privilege = $client->createPrivilege($name, $version, $statements);

/* Update Privilege */
$name = "privilege_example_updated";
$statement2 = new Statement(
    "Allow",
    [
        "apps:List",
    ],
    ["*"]
);
$privilege = $client->updatePrivilege($privilege->id, $name, $version, $statements);

/* Get Privilege */
$privilege = $client->getPrivilege($privilege->id);

/* Delete Privilege */
$result = $client->deletePrivilege($privilege->id);

/* Gets a list of the roles assigned to a privilege */
$assignedRoles = $client->getRolesAssignedToPrivilege($privilege->id);

/* Assign roles to a privilege */
$result = $client->assignRolesToPrivilege($privilege->id, array($role_id1, $role_id2));

/* Remove role from a privilege */
$result = $client->removeRoleFromPrivilege($privilege->id, $role_id1);

/* Gets a list of the users assigned to a privilege */
$assignedUsers = $client->getUsersAssignedToPrivilege($privilege->id);

/* Assign users to a privilege */
$result = $client->assignUsersToPrivilege($privilege->id, array($user_id1, $user_id2));

/* Remove user from a privilege */
$result = $client->removeUserFromPrivilege($privilege->id, $user_id2);

Development

After checking out the repo, run composer install to install dependencies. Then, cd tests and phpunit . to run the tests.

To release a new version, update the version number of the composer.json and commit it, then you will be able to update it to composer, creating a previously a new tag on github.

Contributing

Bug reports and pull requests are welcome on GitHub at https://github.com/onelogin/onelogin-php-sdk. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the Contributor Covenant code of conduct.

License

The gem is available as open source under the terms of the MIT License.

Code of Conduct

Everyone interacting in the OneLogin PHP SDK project’s codebases, issue trackers, chat rooms and mailing lists is expected to follow the code of conduct.

onelogin-php-sdk's People

Contributors

collegeman avatar gwadley avatar jmfwolf avatar pitbulk avatar wmhopk avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

onelogin-php-sdk's Issues

Throw exceptions on error

It would be great if API errors actually resulted in exceptions being thrown. Otherwise we manually have to check for errors after every call.

You could raise the major version or make that behavior configurable to not break compatibility.

Update Packagist

Packagist needs updating to make package compatible with Guzzle 7.

Need to be able to update this as on 8.1

Delete user method fails

Review what is going wrong with the DELETE method on users.

Similar calls in other sdks & curl (checked headers) works, but on php sdk doesn't

Error with getEnrolledFactors($userId)

Proposed patch to OneLoginClient.php :

226c226
<         if (count($data) == 1 && empty($data[0])) {
---
>         if (is_array($data) && count($data) == 1 && empty($data[0])) {
2177a2178,2183
>                     if (!property_exists($otpDeviceData, 'phone_number')) {
>                         $otpDeviceData->phone_number = '';
>                     }
>                     if (!property_exists($otpDeviceData, 'state_token')) {
>                         $otpDeviceData->state_token = '';
>                     }

Bug In How getEnrolledFactors Handles the otp_devices API Data

First, I want to thank you for this SDK. It's been quite helpful to our organization.

I discovered a bug in the OneLogin PHP SDK caused by what I think is an API inconsistency related to the GET /users/{user_id}/otp_devices API endpoint endpoint.

The primary issue is in the OneLoginClient.php file within the methods handleDataResponse and getEnrolledFactors. This also affects getFactors in the same way as getEnrolledFactors.

The issue seems to stem from the fact that the otp_devices endpoint is returning its data wrapped in an extra object with the single property '[otp_devices]=>array(...)' instead of just being a flat array of OTP devices similar to how GET /users is a flat array of the users.

This is causing two issues on line 226--if (count($data) == 1 && empty($data[0])) {--in handleDataResponse. First, count($data) is raising a warning because stdClass objects don't implement the countable interface, and second, since the value of $data is an object, empty($data[0]) is evaluated to true since the data itself is actually in $data->otp_devices. The causes the function to always return an empty array regardless of the data returned by otp_devices.

I've added a bandaid to this for now by circumventing the if check by adding

if (is_object($data)) {
  return $data;
}

on line 227. This appears to work in our environment without raising issues elsewhere, but we don't use a majority of the SDK functions, and the test suite doesn't seem to be mocking (or even touching) any of the SDK's API calls.

In full, "handleDataResponse" now looks like

protected function handleDataResponse($response) {
  $data = null;
  $content = json_decode($response->getBody());
  if (property_exists($content, 'data')) {
    $data = $content->data;
  }
  if (is_object($data)) {
    return $data
  }
  if (count($data) == 1 && empty($data[0])) {
    return [];
  }

  return $data;
}

Upon reflection on this, a better solution to this is likely to cast data to an array and then call array_values on the new array to get numerically indexed keys.

Regardless, having resolved this, another issue popped up in the way the library handles creating new OTPDevice objects. The issue stems from the way fields are added to the object. If the resulting otp_device data doesn't include every field expected by the constructor, the library raises an error which is caught by the catch (\Exception $e) on line 2186 (related to issue 11 in the SDK's github -- not opened by me) and the code returns without creating any OTPDevices.

To resolve this, we've added null coalesce operators with empty string defaults like

public function __construct($data) {
  $this->id = isset($data->id)? (int) $data->id : null;
  $this->active = $data->active ?? '';
  $this->default = $data->default ?? '';
  $this->authFactorName = $data->auth_factor_name ?? '';
  $this->phoneNumber = $data->phone_number ?? '';
  $this->typeDisplayName = $data->type_display_name ?? '';
  $this->needsTrigger = $data->needs_trigger ?? '';
  $this->userDisplayName = $data->user_display_name ?? '';
  $this->stateToken = $data->state_token ?? '';
}

but these fields may need to actually have some real default instead of just empty strings. The issues for me were phone_number and state_token, but I went ahead and headed off future issues for us by adding them to every field.

With these changes, it appears that I'm finally getting valid OTP results.

We created a case with the support team about this (CS0267403) and they pointed us here. I'd be happy to open a PR (or 2) for this with my exact changes above, but I'm hesitant to do that. Primarily, I'm not sure that my PHP code fixes are the best solution. There don't seem to be any unit tests for individual functions--just some to check if the library generally is working--so any change I make could adversely affect other functionality. Additionally, I'm not entirely sure if this project is still maintained (I hope so! This has been really helpful!). The last update was nearly a year ago -- comparing this to the python SDK which seems to still be under active development.

getFactors() Error

The following error is displayed when attempting to getFactors for a User ID

Fatal error: Uncaught TypeError: count(): Argument #1 ($value) must be of type Countable|array, stdClass given in /var/www/test/vendor/onelogin/api/src/OneLoginClient.php:226 Stack trace: #0 /var/www/test/vendor/onelogin/api/src/OneLoginClient.php(226): count() #1 /var/www/test/vendor/onelogin/api/src/OneLoginClient.php(2072): OneLogin\api\OneLoginClient->handleDataResponse() #2 /var/www/test/admin/debug.php(31): OneLogin\api\OneLoginClient->getFactors() #3 {main} thrown in /var/www/test/vendor/onelogin/api/src/OneLoginClient.php on line 226

PHP Code:

$client = new OneLoginClient($clientId, $clientSecret, $region);
$authFactors = $client->getFactors(77149912);
print_r($authFactors);

Isssue when trying to sort getUsers()

From the OneLogin API Reference:
OneLogin API - Users

Return users sorted by firstname. Use + to sort in ascending order or - to sort in descending order:
https://api.us.onelogin.com/api/2/users?sort=+firstname

Attempted code

$queryParameters = [
	"sort" => "+firstname"
];
$userList = $oneLoginApi->getUsers($queryParameters);

Returns:
Empty array (blank)

For now the workaround is to just leave sort blank but I assume I am either doing this wrong or it is something to do with character encoding but as it isn't documented I can't be sure

$queryParameters = [
	"sort" => ""
];
$userList = $oneLoginApi->getUsers($queryParameters);

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.