diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..d8fe4fa --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +/.project diff --git a/README.md b/README.md index 00367fb..a25edb7 100644 --- a/README.md +++ b/README.md @@ -10,8 +10,31 @@ Requires: - PingOne account with PingID service enabled (visit [Ping Identity Developer Site] to get a developer account) ### Installation - -1. Execute the scripts from your command line (ie php getUserDetails.php jsmith) + +1. Enable 3rd-party Client Integration in the PingOne Admin Web GUI (Setup -> PingID -> Client Integration -> Third-party Clients -> Enable). +2. Download the `pingid.properties` file from PingOne (Setup -> PingID -> Client Integration -> Settings File -> Download) and put in in the scripts directory. +3. Execute the scripts from your command line i.e. `php getUserDetails.php jsmith` + +### Workflows + +1a. Enroll user with mobile device +- `php addUser jdoe John Doe hzandbelt+johndoe@pingidentity.com` +*pickup pairing key or QR code URL from output* +- `php getUserDetails.php jdoe` + +1b. Add e-mail OTP +- `php startOfflinePairing.php jdoe EMAIL hzandbelt+johndoe@pingidentity.com` +- `php finalizeOfflinePairing.php ` + +2a. Enroll user with e-mail OTP +- `php addUser.php jdoe John Doe hzandbelt+johndoe@pingidentity.com false` +- `php startOfflinePairing.php jdoe EMAIL hzandbelt+johndoe@pingidentity.com` +- `php finalizeOfflinePairing.php ` + +2b. Add mobile device later +- `php getActivationCode.php jdoe` +*pickup pairing key or QR code URL from output* +- `php getPairingStatus.php ` ### Disclaimer diff --git a/scripts/Utils.php b/scripts/Utils.php new file mode 100755 index 0000000..735964f --- /dev/null +++ b/scripts/Utils.php @@ -0,0 +1,93 @@ + 'HS256', + 'org_alias' => $org_alias, + 'token' => $token + ); + $segments = array(); + $segments[] = pingid_base64url_encode(json_encode($header)); + $segments[] = pingid_base64url_encode(json_encode($payload)); + $segments[] = pingid_base64url_encode(hash_hmac('SHA256', implode('.', $segments), $key, true)); + return implode('.', $segments); +} + +function pingid_get_timestamp() { + $MDT = 3600 * -6; + return gmdate("Y-m-d H:i:s.000", time() + $MDT); +} + +function pingid_send_request($props, $path, $body) { + $jwt = array( + 'reqHeader' => array( + 'orgAlias' => $props['org_alias'], + 'secretKey' => $props['token'], + 'timestamp' => pingid_get_timestamp(), + 'version' => PINGID_API_VERSION, + 'locale' => 'en', + 'sessionId' => null + ), + 'reqBody' => $body + ); + + $data = pingid_jwt_encode( + $jwt, + base64_decode($props['use_base64_key']), + $props['org_alias'], + $props['token']); + + $api_url = $props['admin_url'] . '/rest/4/' . $path; + + #echo + #print_r($data); + #echo + + $headers = array(); + $headers[] = 'Content-Type: application/json'; + $ch = curl_init($api_url); + curl_setopt($ch, CURLOPT_VERBOSE, true); + curl_setopt($ch, CURLOPT_POSTFIELDS, $data); + curl_setopt($ch, CURLOPT_HTTPHEADER, $headers); + curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); + $result = curl_exec($ch); + curl_close($ch); + + return $result; +} + +function pingid_exec_command($prop_file, $cmd_path, $req_array) { + $props = parse_ini_file($prop_file, false, INI_SCANNER_RAW); + $req_array['clientData'] = null; + $jwt = pingid_send_request($props, $cmd_path . '/do', $req_array); + list($headb64, $bodyb64, $cryptob64) = explode('.', $jwt); + return pingid_base64url_decode($bodyb64); +} + +?> diff --git a/scripts/addUser.php b/scripts/addUser.php new file mode 100755 index 0000000..6e8c090 --- /dev/null +++ b/scripts/addUser.php @@ -0,0 +1,40 @@ + [true|false]\n"; + exit; +} + +$props_file = 'pingid.properties'; + +$response = pingid_exec_command($props_file, 'adduser', array( + 'activateUser' => count($argv) > 5 ? $argv[5] == "true" : "true", + 'email' => $argv[4], + 'fName' => $argv[2], + 'lname' => $argv[3], + 'userName' => $argv[1], + 'role' => 'REGULAR' +)); +print $response; + +$props = parse_ini_file($props_file, false, INI_SCANNER_RAW); + +$json = json_decode($response); +print "\n\n # Activation code is: " . $json->responseBody->activationCode . "\n"; +print " # QR Code URL is: " . $props['admin_url'] . '/QRRedirection?' . base64_encode('act_code=' . $json->responseBody->activationCode) . "\n"; + +?> diff --git a/scripts/authenticateOnline.php b/scripts/authenticateOnline.php new file mode 100755 index 0000000..94df83e --- /dev/null +++ b/scripts/authenticateOnline.php @@ -0,0 +1,28 @@ +\n"; + exit; +} + +print pingid_exec_command('pingid.properties', 'authonline', array( + 'authType' => 'CONFIRM', + 'spAlias' => 'web', + 'userName' => $argv[1] +)); + +?> diff --git a/scripts/deleteUser.php b/scripts/deleteUser.php new file mode 100755 index 0000000..bd984df --- /dev/null +++ b/scripts/deleteUser.php @@ -0,0 +1,26 @@ +\n"; + exit; +} + +print pingid_exec_command('pingid.properties', 'deleteuser', array( + 'userName' => $argv[1] +)); + +?> diff --git a/scripts/finalizeOfflinePairing.php b/scripts/finalizeOfflinePairing.php new file mode 100755 index 0000000..61f3cae --- /dev/null +++ b/scripts/finalizeOfflinePairing.php @@ -0,0 +1,27 @@ + \n"; + exit; +} + +print pingid_exec_command('pingid.properties', 'finalizeofflinepairing', array( + 'sessionId' => $argv[1], + 'otp' => $argv[2] +)); + +?> diff --git a/scripts/getActivationCode.php b/scripts/getActivationCode.php new file mode 100755 index 0000000..be4287e --- /dev/null +++ b/scripts/getActivationCode.php @@ -0,0 +1,35 @@ +\n"; + exit; +} + +$props_file = 'pingid.properties'; + +$response = pingid_exec_command($props_file, 'getactivationcode', array( + 'userName' => $argv[1] +)); +print $response; + +$props = parse_ini_file($props_file, false, INI_SCANNER_RAW); + +$json = json_decode($response); +print "\n\n # Activation code is: " . $json->responseBody->activationCode . "\n"; +print " # QR Code URL is: " . $props['admin_url'] . '/QRRedirection?' . base64_encode('act_code=' . $json->responseBody->activationCode) . "\n"; + +?> diff --git a/scripts/getPairingStatus.php b/scripts/getPairingStatus.php new file mode 100755 index 0000000..a7236f1 --- /dev/null +++ b/scripts/getPairingStatus.php @@ -0,0 +1,26 @@ +\n"; + exit; +} + +print pingid_exec_command('pingid.properties', 'pairingstatus', array( + 'activationCode' => $argv[1] +)); + +?> diff --git a/scripts/getUserDetails.php b/scripts/getUserDetails.php index 5a9ab43..0d2b6d3 100755 --- a/scripts/getUserDetails.php +++ b/scripts/getUserDetails.php @@ -12,75 +12,16 @@ this directory. */ -function pingid_base64url_encode($input) { - return str_replace('=', '', strtr(base64_encode($input), '+/', '-_')); -} - -function pingid_jwt_encode($payload, $key, $org_alias, $token) { - $header = array( - 'alg' => 'HS256', - 'org_alias' => $org_alias, - 'token' => $token - ); - $segments = array(); - $segments[] = pingid_base64url_encode(json_encode($header)); - $segments[] = pingid_base64url_encode(json_encode($payload)); - $segments[] = pingid_base64url_encode(hash_hmac('SHA256', implode('.', $segments), $key, true)); - return implode('.', $segments); -} - -function pingid_get_timestamp() { - $MDT = 3600 * -6; - return gmdate("Y-m-d H:i:s.000", time() + $MDT); -} - -function pingid_send_request($props, $path, $body) { - $jwt = array( - 'reqHeader' => array( - 'orgAlias' => $props['org_alias'], - 'secretKey' => $props['token'], - 'timestamp' => pingid_get_timestamp(), - 'version' => '4.6', - 'locale' => 'en', - 'sessionId' => null - ), - 'reqBody' => $body - ); - - $data = pingid_jwt_encode( - $jwt, - base64_decode($props['use_base64_key']), - $props['org_alias'], - $props['token']); - - $headers = array(); - $headers[] = 'Content-Type: application/json'; - $ch = curl_init($props['api-base-url'] . $path); - curl_setopt($ch, CURLOPT_VERBOSE, true); - curl_setopt($ch, CURLOPT_POSTFIELDS, $data); - curl_setopt($ch, CURLOPT_HTTPHEADER, $headers); - $result = curl_exec($ch); - curl_close($ch); - - return $result; -} - -function pingid_get_user_details($props, $username) { - return pingid_send_request($props, 'getuserdetails/do', array( - 'getSameDeviceUsers' => true, - 'userName' => $username, - 'clientData' => null - )); -} +require_once 'Utils.php'; if (count($argv) < 2) { echo "Usage: $argv[0] \n"; exit; } -$props = parse_ini_file('pingid.properties', false, INI_SCANNER_RAW); -$props['api-base-url'] = 'https://idpxnyl3m.pingidentity.com/pingid/rest/4/'; - -print pingid_get_user_details($props, $argv[1]); +print pingid_exec_command('pingid.properties', 'getuserdetails', array( + 'getSameDeviceUsers' => true, + 'userName' => $argv[1] +)); ?> diff --git a/scripts/startAuthentication.php b/scripts/startAuthentication.php new file mode 100755 index 0000000..b54f23f --- /dev/null +++ b/scripts/startAuthentication.php @@ -0,0 +1,27 @@ +\n"; + exit; +} + +print pingid_exec_command('pingid.properties', 'startauthentication', array( + 'spAlias' => 'web', + 'userName' => $argv[1] +)); + +?> diff --git a/scripts/startOfflinePairing.php b/scripts/startOfflinePairing.php new file mode 100755 index 0000000..d36adb1 --- /dev/null +++ b/scripts/startOfflinePairing.php @@ -0,0 +1,32 @@ + [SMS | VOICE | EMAIL ]\n"; + exit; +} + +$response = pingid_exec_command('pingid.properties', 'startofflinepairing', array( + 'username' => $argv[1], + 'type' => $argv[2], + 'pairingData' => $argv[3] +)); +print $response; + +$json = json_decode($response); +print "\n\n # sessionId is: " . $json->responseBody->sessionId . "\n"; + +?>