From 0a2b099e501fc433985728c59bf6fbb5cca1209d Mon Sep 17 00:00:00 2001 From: lukasmatusiewicz Date: Wed, 6 Sep 2023 12:58:08 +0200 Subject: [PATCH] 41 feature forward headers (#42) * forward headers implementation * update tests * update tests * Update PrivacyIDEA.php --- src/PrivacyIDEA.php | 76 +++++++++++++++++++++++------- test/EnrollTokenTest.php | 3 +- test/PollTransactionTest.php | 4 +- test/TriggerChallengeTest.php | 2 +- test/ValidateCheckTest.php | 2 +- test/ValidateCheckU2FTest.php | 4 +- test/ValidateCheckWebauthnTest.php | 2 +- 7 files changed, 69 insertions(+), 24 deletions(-) diff --git a/src/PrivacyIDEA.php b/src/PrivacyIDEA.php index a6063c9..bf929b0 100644 --- a/src/PrivacyIDEA.php +++ b/src/PrivacyIDEA.php @@ -62,10 +62,11 @@ public function __construct($userAgent, $serverURL) * @param $username string * @param $pass string this can be the OTP, but also the PIN to trigger a token or PIN+OTP depending on the configuration of the server. * @param null $transactionID Optional transaction ID. Used to reference a challenge that was triggered beforehand. + * @param null $headers Optional headers array to forward to the server. * @return PIResponse|null null if response was empty or malformed, or parameter missing * @throws PIBadRequestException */ - public function validateCheck($username, $pass, $transactionID = null) + public function validateCheck($username, $pass, $transactionID = null, $headers=null) { assert('string' === gettype($username)); assert('string' === gettype($pass)); @@ -79,12 +80,16 @@ public function validateCheck($username, $pass, $transactionID = null) // Add transaction ID in case of challenge response $params["transaction_id"] = $transactionID; } + if (empty($headers)) + { + $headers = array(''); + } if ($this->realm) { $params["realm"] = $this->realm; } - $response = $this->sendRequest($params, array(''), 'POST', '/validate/check'); + $response = $this->sendRequest($params, $headers, 'POST', '/validate/check'); $ret = PIResponse::fromJSON($response, $this); if ($ret == null) @@ -105,17 +110,18 @@ public function validateCheck($username, $pass, $transactionID = null) * This function requires a service account to be set. * * @param string $username + * @param null $headers Optional headers array to forward to the server. * @return PIResponse|null null if response was empty or malformed, or parameter missing * @throws PIBadRequestException */ - public function triggerChallenge($username) + public function triggerChallenge($username, $headers = null) { assert('string' === gettype($username)); if ($username) { $authToken = $this->getAuthToken(); - $header = array("authorization:" . $authToken); + $authTokenHeader = array("authorization:" . $authToken); $params = array("user" => $username); @@ -124,7 +130,16 @@ public function triggerChallenge($username) $params["realm"] = $this->realm; } - $response = $this->sendRequest($params, $header, 'POST', '/validate/triggerchallenge'); + if (!empty($headers)) + { + $headers = array_merge($headers, $authTokenHeader); + } + else + { + $headers = $authTokenHeader; + } + + $response = $this->sendRequest($params, $headers, 'POST', '/validate/triggerchallenge'); return PIResponse::fromJSON($response, $this); } @@ -139,17 +154,22 @@ public function triggerChallenge($username) * Poll for the status of a transaction (challenge). * * @param $transactionID string transactionId of the push challenge that was triggered before + * @param null $headers Optional headers array to forward to the server. * @return bool true if the Push request has been accepted, false otherwise. * @throws PIBadRequestException */ - public function pollTransaction($transactionID) + public function pollTransaction($transactionID, $headers = null) { assert('string' === gettype($transactionID)); if (!empty($transactionID)) { $params = array("transaction_id" => $transactionID); - $responseJSON = $this->sendRequest($params, array(''), 'GET', '/validate/polltransaction'); + if (empty($headers)) + { + $headers = array(''); + } + $responseJSON = $this->sendRequest($params, $headers, 'GET', '/validate/polltransaction'); $response = json_decode($responseJSON, true); return $response['result']['value']; } @@ -167,10 +187,11 @@ public function pollTransaction($transactionID) * @param string $genkey * @param string $type * @param string $description + * @param null $headers Optional headers array to forward to the server. * @return mixed Object representing the response of the server or null if parameters are missing * @throws PIBadRequestException */ - public function enrollToken($username, $genkey, $type, $description = "") // No return type because mixed not allowed yet + public function enrollToken($username, $genkey, $type, $description = "", $headers = null) // No return type because mixed not allowed yet { assert('string' === gettype($username)); assert('string' === gettype($type)); @@ -196,10 +217,18 @@ public function enrollToken($username, $genkey, $type, $description = "") // No $authToken = $this->getAuthToken(); // If error occurred in getAuthToken() - return this error in PIResponse object - $header = array("authorization:" . $authToken); + $authTokenHeader = array("authorization:" . $authToken); + if (!empty($headers)) + { + $headers = array_merge($headers, $authTokenHeader); + } + else + { + $headers = $authTokenHeader; + } // Check if user has token - $tokenInfo = json_decode($this->sendRequest(array("user" => $username, "realm" => $params["realm"]), $header, 'GET', '/token')); + $tokenInfo = json_decode($this->sendRequest(array("user" => $username, "realm" => $params["realm"]), $headers, 'GET', '/token')); if (!empty($tokenInfo->result->value->tokens)) { @@ -209,7 +238,7 @@ public function enrollToken($username, $genkey, $type, $description = "") // No else { // Call /token/init endpoint and return the response - return json_decode($this->sendRequest($params, $header, 'POST', '/token/init')); + return json_decode($this->sendRequest($params, $headers, 'POST', '/token/init')); } } @@ -220,10 +249,11 @@ public function enrollToken($username, $genkey, $type, $description = "") // No * @param string $transactionID * @param string $webAuthnSignResponse * @param string $origin + * @param null $headers Optional headers array to forward to the server. * @return PIResponse|null returns null if the response was empty or malformed * @throws PIBadRequestException */ - public function validateCheckWebAuthn($username, $transactionID, $webAuthnSignResponse, $origin) + public function validateCheckWebAuthn($username, $transactionID, $webAuthnSignResponse, $origin, $headers = null) { assert('string' === gettype($username)); assert('string' === gettype($transactionID)); @@ -259,9 +289,17 @@ public function validateCheckWebAuthn($username, $transactionID, $webAuthnSignRe $params[ASSERTIONCLIENTEXTENSIONS] = $tmp[ASSERTIONCLIENTEXTENSIONS]; } - $header = array("Origin:" . $origin); + $originHeader = array("Origin:" . $origin); + if (!empty($headers)) + { + $headers = array_merge($headers, $originHeader); + } + else + { + $headers = $originHeader; + } - $response = $this->sendRequest($params, $header, 'POST', '/validate/check'); + $response = $this->sendRequest($params, $headers, 'POST', '/validate/check'); return PIResponse::fromJSON($response, $this); } @@ -279,10 +317,11 @@ public function validateCheckWebAuthn($username, $transactionID, $webAuthnSignRe * @param string $username * @param string $transactionID * @param string $u2fSignResponse + * @param null $headers Optional headers array to forward to the server. * @return PIResponse|null * @throws PIBadRequestException */ - public function validateCheckU2F($username, $transactionID, $u2fSignResponse) + public function validateCheckU2F($username, $transactionID, $u2fSignResponse, $headers = null) { assert('string' === gettype($username)); assert('string' === gettype($transactionID)); @@ -301,12 +340,17 @@ public function validateCheckU2F($username, $transactionID, $u2fSignResponse) $params["realm"] = $this->realm; } + if (!empty($headers)) + { + $headers = array(''); + } + // Additional U2F params from $u2fSignResponse $tmp = json_decode($u2fSignResponse, true); $params[CLIENTDATA] = $tmp["clientData"]; $params[SIGNATUREDATA] = $tmp["signatureData"]; - $response = $this->sendRequest($params, array(), 'POST', '/validate/check'); + $response = $this->sendRequest($params, $headers, 'POST', '/validate/check'); return PIResponse::fromJSON($response, $this); } diff --git a/test/EnrollTokenTest.php b/test/EnrollTokenTest.php index 5d26446..0fe0b65 100644 --- a/test/EnrollTokenTest.php +++ b/test/EnrollTokenTest.php @@ -71,7 +71,8 @@ public function testSuccess() "testUser", "1", "totp", - "Enrolled for test"); + "Enrolled for test", + array('accept-language:en')); $this->assertNotNull($response); $this->assertIsObject($response); diff --git a/test/PollTransactionTest.php b/test/PollTransactionTest.php index 80d947e..46f4392 100644 --- a/test/PollTransactionTest.php +++ b/test/PollTransactionTest.php @@ -51,7 +51,7 @@ public function testTriggerPushToken() ->end(); $this->http->setUp(); - $response = $this->pi->validateCheck("testUser", "testPass"); + $response = $this->pi->validateCheck("testUser", "testPass", null, array('accept-language:en')); $this->assertEquals("Bitte geben Sie einen OTP-Wert ein: , Please confirm the authentication on your mobile device!", $response->message); $this->assertEquals("Bitte geben Sie einen OTP-Wert ein: , Please confirm the authentication on your mobile device!", $response->messages); @@ -80,7 +80,7 @@ public function testSuccess() ->end(); $this->http->setUp(); - $response = $this->pi->pollTransaction("1234567890"); + $response = $this->pi->pollTransaction("1234567890", array('accept-language:en')); $this->assertNotNull($response); $this->assertTrue($response); diff --git a/test/TriggerChallengeTest.php b/test/TriggerChallengeTest.php index fbfaed0..84f9c05 100644 --- a/test/TriggerChallengeTest.php +++ b/test/TriggerChallengeTest.php @@ -87,7 +87,7 @@ public function testTriggerChallengeSuccess() */ public function testNoServiceAccount() { - $response = $this->pi->triggerchallenge("testUser"); + $response = $this->pi->triggerchallenge("testUser", array('accept-language:en')); $this->assertNull($response); } diff --git a/test/ValidateCheckTest.php b/test/ValidateCheckTest.php index d53c15f..5a92b6e 100644 --- a/test/ValidateCheckTest.php +++ b/test/ValidateCheckTest.php @@ -54,7 +54,7 @@ public function testOTPSuccess() ->end(); $this->http->setUp(); - $response = $this->pi->validateCheck("testUser", "testPass"); + $response = $this->pi->validateCheck("testUser", "testPass", null, array('accept-language:en')); $this->assertEquals("matching 1 tokens", $response->message); $this->assertEquals(Utils::matchingOneTokenResponseBody(), $response->raw); diff --git a/test/ValidateCheckU2FTest.php b/test/ValidateCheckU2FTest.php index 1085177..e929e78 100644 --- a/test/ValidateCheckU2FTest.php +++ b/test/ValidateCheckU2FTest.php @@ -51,7 +51,7 @@ public function testTriggerU2F() ->end(); $this->http->setUp(); - $response = $this->pi->validateCheck("testUser", "testPass"); + $response = $this->pi->validateCheck("testUser", "testPass", null, array('accept-language:en')); $this->assertEquals("Please confirm with your U2F token (Yubico U2F EE Serial 61730834)", $response->message); $this->assertEquals("Please confirm with your U2F token (Yubico U2F EE Serial 61730834)", $response->messages); @@ -82,7 +82,7 @@ public function testSuccess() ->end(); $this->http->setUp(); - $response = $this->pi->validateCheckU2F("testUser", "12345678", Utils::u2fSignResponse()); + $response = $this->pi->validateCheckU2F("testUser", "12345678", Utils::u2fSignResponse(), array('accept-language:en')); $this->assertEquals("matching 1 tokens", $response->message); $this->assertEquals(Utils::matchingOneTokenResponseBody(), $response->raw); diff --git a/test/ValidateCheckWebauthnTest.php b/test/ValidateCheckWebauthnTest.php index 021c195..a795108 100644 --- a/test/ValidateCheckWebauthnTest.php +++ b/test/ValidateCheckWebauthnTest.php @@ -84,7 +84,7 @@ public function testSuccess() ->end(); $this->http->setUp(); - $response = $this->pi->validateCheckWebAuthn("testUser", "12345678", Utils::webauthnSignResponse(), "test.it"); + $response = $this->pi->validateCheckWebAuthn("testUser", "12345678", Utils::webauthnSignResponse(), "test.it", array('accept-language:en')); $this->assertNotNull($response); $this->assertEquals(Utils::matchingOneTokenResponseBody(), $response->raw);