Add samlp:extensions to authsources.php SimpleSamlPHP - php

What I wish to accomplish is adding the following example to Authnrequest
<samlp:Extensions>
<somens:TheExtensionName xmlns:somens="http://uriofextension/">
<somens:TheExtensionName Name="AttributeName" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri"
isRequired="true"/>
</somens:TheExtensionName >
</samlp:Extensions>
By using authsource.php, how am I able to accomplish that?
I've read the documentation and at the point
https://simplesamlphp.org/docs/stable/saml:sp
5.8 Using samlp:Extensions
They have:
$dom = \SAML2\DOMDocumentFactory::create();
$ce = $dom->createElementNS('http://www.example.com/XFoo', 'xfoo:test', 'Test data!');
$ext[] = new \SAML2\XML\Chunk($ce);
$auth = new \SimpleSAML\Auth\Simple('default-sp');
$auth->login(array(
'saml:Extensions' => $ext,
));
But where is this code included? As I've added it to the authsources.php without luck, and can't figure out how to use this, consider also my lack of knowledge regarding php, so maybe im just messing things.
This is what I've tried in authsources.php
Disregard some parts of the code that belong to the examples provided
<?php
$dom = \SAML2\DOMDocumentFactory::create();
$ce = $dom->createElementNS('http://www.example.com/XFoo', 'xfoo:test', 'Test data!');
$ext[] = new \SAML2\XML\Chunk($ce);
$config = array(
'sp.name' => array(
'saml:SP',
'privatekey' => '/certs/privkey.pem',
'certificate' => '/certs/fullchain.pem',
'entityID' => 'entityID',
'idp' => 'idpID',
'saml:Extensions' => $ext,
),
);

Well I've not been able to use authsources.php yet, but managed to recreate it with the samlp:extensions authnrequest I needed.
I've created an php app and connected that to Simplesaml Service Provider in order to send the request with samlp:Extensions and here is a code for those having the same issue:
app/app.php
<?php
//Load SimpleSAMLphp.
require_once('/var/www/simplesamlphp/lib/_autoload.php');
//Initiate a SimpleSAML_Auth_Simple object.
$as = new SimpleSAML_Auth_Simple('name-of-sp');
//Standard PHP lib more info at -> http://php.net/manual/en/domdocument.createelementns.phphttp://php.net/manual/en/domdocument.createelementns.php
$dom = SAML2_DOMDocumentFactory::create();
$attributes_ext = $dom->createElementNS('namespace-uri', 'fa:RequestedAttributes');
$item = $dom->createElementNS('namespace-uri', 'fa:RequestedAttribute');
$attrName = $dom->createAttribute('Name');
$attrName->value = 'attributeName';
$attrNameFormat = $dom->createAttribute('NameFormat');
$attrNameFormat->value = "urn:oasis:names:tc:SAML:2.0:attrname-format:uri";
$attrRequirement = $dom->createAttribute('isRequired');
$attrRequirement->value = "true";
$item->appendChild($attrName);
$item->appendChild($attrNameFormat);
$item->appendChild($attrRequirement);
$attributes_ext->appendChild($item);
$ext[] = new SAML2_XML_Chunk($attributes_ext);
$as->login(array(
'saml:Extensions' => $ext,
));
//If the user is not authenticated, authenticate the user
$as->requireAuth();
//Get the users attributes and print them.
$attributes = $as->getAttributes();
print_r($attributes);
//Output the attributes to a file
$myFile = "/tmp/attributes.log";
$fh = fopen($myFile, 'a') or die("can't open file");
$stringData = print_r($attributes, true);
fwrite($fh, $stringData);
fclose($fh);
//Displays a Login and Logout link
$url_in = $as->getLoginURL();
$url_out = $as->getLogoutURL();
print('<br>Login');
print('<br>Logout<br>');
//If using PHP sessions in SimpleSAMLphp cleanup the SimpleSAMLphp session to be able to use $_SESSION
$session = SimpleSAML_Session::getSessionFromRequest();
$session->cleanup();
//Display PHP information
phpinfo()
?>
</body>
</html>
To set it to run for experiment
php -S 0.0.0.0:5000 -t app/
Navigate to localhost:5000/app.php, this will automatically send you to the login of the IDP, using the SP configurations. You can try with authsources.php examples provided by simplesamlphp

Related

How to MODIFY a Google Docs document via API using search-and-replace?

I need an example of how to modify an existing document with existing text in Google Docs via API. The documentation only shows how to insert and delete text, but not how to update. Have been looking frantically on the web to find examples or a direction on how to do it but without luck.
Finally figured it out myself.
First, follow this video to prepare authentication to the Google Docs API (even though it's about Google Sheets but the process is basically the same). Basically it consists of these steps:
create project in Google Developer Console
enable Google Docs API
create credentials, including a service account for programmatic access
share your document with the service account client email address
install Google API's PHP client: composer require google/apiclient
Then create a script like the following:
require_once(__DIR__ .'/vendor/autoload.php');
$client = new \Google_Client();
$client->setApplicationName('Some name'); //this name doesn't matter
$client->setScopes([\Google_Service_Docs::DOCUMENTS]);
$client->setAccessType('offline');
$client->setAuthConfig(__DIR__ .'/googleapi-credentials.json'); //see https://www.youtube.com/watch?v=iTZyuszEkxI for how to create this file
$service = new \Google_Service_Docs($client);
$documentId = 'YOUR-DOCUMENT-ID-GOES-HERE'; //set your document ID here, eg. "j4i1m57GDYthXKqlGce9WKs4tpiFvzl1FXKmNRsTAAlH"
$doc = $service->documents->get($documentId);
// Collect all pieces of text (see https://developers.google.com/docs/api/concepts/structure to understand the structure)
$allText = [];
foreach ($doc->body->content as $structuralElement) {
if ($structuralElement->paragraph) {
foreach ($structuralElement->paragraph->elements as $paragraphElement) {
if ($paragraphElement->textRun) {
$allText[] = $paragraphElement->textRun->content;
}
}
}
}
// Go through and create search/replace requests
$requests = $textsAlreadyDone = $forEasyCompare = [];
foreach ($allText as $currText) {
if (in_array($currText, $textsAlreadyDone, true)) {
// If two identical pieces of text are found only search-and-replace it once - no reason to do it multiple times
continue;
}
if (preg_match_all("/(.*?)(dogs)(.*?)/", $currText, $matches, PREG_SET_ORDER)) {
//NOTE: for simple static text searching you could of course just use strpos()
// - and then loop on $matches wouldn't be necessary, and str_replace() would be simplified
$modifiedText = $currText;
foreach ($matches as $match) {
$modifiedText = str_replace($match[0], $match[1] .'cats'. $match[3], $modifiedText);
}
$forEasyCompare[] = ['old' => $currText, 'new' => $modifiedText];
$replaceAllTextRequest = [
'replaceAllText' => [
'replaceText' => $modifiedText,
'containsText' => [
'text' => $currText,
'matchCase' => true,
],
],
];
$requests[] = new \Google_Service_Docs_Request($replaceAllTextRequest);
}
$textsAlreadyDone[] = $currText;
}
// you could dump out $forEasyCompare to see the changes that would be made
$batchUpdateRequest = new \Google_Service_Docs_BatchUpdateDocumentRequest(['requests' => $requests]);
$response = $service->documents->batchUpdate($documentId, $batchUpdateRequest);
This is my way - easy one
public function replaceText($search, $replace)
{
$client = $this->getClient();
$service = new \Google_Service_Docs($client);
$documentId = ''; // Put your document ID here
$e = new \Google_Service_Docs_SubstringMatchCriteria();
$e->text = "{{".$search."}}";
$e->setMatchCase(false);
$requests[] = new \Google_Service_Docs_Request(array(
'replaceAllText' => array(
'replaceText' => $replace,
'containsText' => $e
),
));
$batchUpdateRequest = new \Google_Service_Docs_BatchUpdateDocumentRequest(array(
'requests' => $requests
));
$response = $service->documents->batchUpdate($documentId, $batchUpdateRequest);
}

Get data to/from secondary PHP file - works with some data, not with other

I have a SPA (react) that is uses PHP calls to connect to a MongoDB.
Works great.
However, due to 'rules' I need to serve the javascript files from a different server -- a server that supports neither MongoDB nor MongoDB php client. Let's call this server, SERVER_A.
Let's call the server hosting the MongoDB PHP client and the MongoDB, SERVER_B. ('B' for 'backend'... :) )
The solution, I believe, was to build a php 'middleman' on SERVER_A that simply passes data on to SERVER_B. Research shows me that file_get_contents is the tool for this.
So I take my original known-working PHP file, I put it on SERVER_B and rename it to "mongoPatch_backend.php".
<?php
$user = "xxxx";
$pwd = 'xxx';
$filter = [];
if (isset($_REQUEST['needleKey'])) {
$needleKey = $_REQUEST['needleKey'];
$needle = $_REQUEST['needle'];
$filter = [$needleKey => $needle];
}
$newData = $_REQUEST['newData'];
$filter = ['x' => ['$gt' => 1]];
$options = [
'projection' => ['_id' => 0],
'sort' => ['x' => -1],
];
$bson = MongoDB\BSON\fromJSON($newData);
$value = MongoDB\BSON\toPHP($bson);
$manager = new MongoDB\Driver\Manager("mongodb://${user}:${pwd}#SERVER_B:27017");
$bulk = new MongoDB\Driver\BulkWrite;
$bulk->update(
[$needleKey => $needle],
['$set' => $value],
['multi' => false, 'upsert' => true]
);
$results = $manager->executeBulkWrite('sedwe.users', $bulk);
var_dump($results);
?>
On SERVER_A I then make a new file, dbPatch.php, like so:
<?php
$API = "https://SERVER_B/php/mongoPatch_backend.php?";
if (isset($_REQUEST['needleKey'])) {
$needleKey = $_REQUEST['needleKey'];
$needle = $_REQUEST['needle'];
$filter = [$needleKey => $needle];
}
$newData = $_REQUEST['newData'];
$postData = "needleKey=".urlencode($needleKey);
$postData .= "&needle=".urlencode($needle);
$postData .= "&newData=".urlencode($newData);
// echo $API.$postData;
$data = file_get_contents($API.$postData);
echo $data;
?>
But when I call it, I get nothing echo'd back out of $data.
Any idea why? Remember, the exact same call directly to mongoPatch_backend.php works just fine (but it's a CORS call, so it's not a valid option).
So here is what I've tried:
First, to ensure my AJAX call was still working, I spit out the response to the console. I get nothing.
So I changed the last line of the middleman (dbPatch.php) to echo "Hello World" instead of echo $data and received "Hello World" on the console as expected.
Next, I then changed the last line of my middleman (dbPatch.php) back to echo $data and tried reducing the 'backend' to a simple <?php echo "Hello Back World"; ?> and got nothing on the console.
Next, I go to https://SERVER_B/php/mongoPatch_backend.php in a browser ... and I'm greeted with "Hello Back World" as expected in the browser.
... which leads me to believe something is up with the transferring of info from server to server. Logical call, eh?
Unfortunately, when I try the same thing with just a 'fetch' command, it works perfectly fine:
Here is my 'middleman' (dbFetch.php) script on SERVER_A:
<?php
$API = "https://SERVER_B/php/mongoFetch_backend.php?";
$collection = $_REQUEST['collection'];
$postData = "collection=".urlencode($collection);
$needleID = $_REQUEST['needleID'];
$postData .= "&needleID=".urlencode($needleID);
$data = file_get_contents($API.$postData);
echo $data;
?>
And this is the file on the backend, SERVER_B:
<?php
$user = "xxxx";
$pwd = 'xxxx';
$filter = [];
if (isset($_REQUEST['needleID'])) {
$needleID = $_REQUEST['needleID'];
$filter = ['id'=> $needleID];
}
if (isset($_REQUEST['collection'])) {
$collection = $_REQUEST['collection'];
}
//Manager Class
$connection = new MongoDB\Driver\Manager("mongodb://${user}:${pwd}#SERVER_B:27017");
// Query Class
$query = new MongoDB\Driver\Query($filter);
$rows = $connection->executeQuery("db_name.$collection", $query);
// Convert rows to Array and send result back to client
$rowsArr = $rows->toArray();
echo json_encode($rowsArr);
?>
Huzzah, this works! ... and it's also proof there doesn't appear to be a problem with the server-to-server communication.
So back to ground zero.
I then go with a very simple newData value -- shorter, but same general layout - stringified json. It works! The data ends up in the database.
So I'm forced to think something is wrong with the data in newData (which is only a few hundred lines of stringified JSON made like this: encodeURIComponent(JSON.stringify(newData)). But, this bears repeating: this works if I skip the middleman.
... and that puts me at a loss. PHP isn't something I understand well... can you help?
EDIT to answer comment:
When I call mongoPatch_backend.php directly on SERVER_B it works (as stated above). I had it echo the $newData and it spits out a stringified JSON version of the variable (not URLencoded).
When I call dbPatch.php, it does not give me anything that was passed back from mongoPatch_backend.
As I said in the OP, if I modify mongoPatch_backend.php to do nothing other than echo "hellow world" I am still unable to log it to console when calling it via the above dbPatch.php file.
EDIT: I also tried putting the two PHP files on the same server and am getting the same results. (ie: both the dbPatch.php and mongoPatch.php files are in the same directory on the same server)
EDIT2: I have done a var_dump from the middleman and I get standard-looking human-readable stringified text back.
I do the same var_dump($_REQUEST['newData']); in the backend file and I get nothing back.

Is there a way to download a file from Google Cloud Storage in PHP ? Instead of just reading it

Is there a way to download a file from Google Cloud Storage in PHP,instead of just reading it and save the content to a file using php functions ?
My code is this:
$obj = new Google_Service_Storage_StorageObject();
$obj->setName($file);
$storage = new Google_Service_Storage($this->gcsClient);
$object = $storage->objects->get($this->bucket, $file);
$request = new Google_Http_Request($object['mediaLink'], 'GET');
$signed_request = $this->gcsClient->getAuth()->sign($request);
$http_request = $this->gcsClient->getIo()->makeRequest($signed_request);
$options = ['gs' => ['Content-Type' => 'text/plain']];
echo $http_request->getResponseBody();
$ctx = stream_context_create($options);
file_put_contents($destination, $http_request->getResponseBody(),0,$ctx);
I've found that Google Cloud Storage supports uploading . I use $storage->objects->insert(...) which works fine,but I can't find a similar function to use for download.
Thank you!
<?php
CloudStorageTools::serve('gs://mybucket/myfile.txt',
['save_as' => 'myfile.txt',
'content_type' => 'text/plain']););
See also the documentation and Stuart Langley's answer to this question.

Error "Class 'Zend_Config_Writer_Xml' not found" when integrate Zend libary into CodeIgniter?

I copy some Zend libraries and paste them into libraries folder in CodeIgniter. I try to use this code, it's ok:
$this->zend->load('zend/json');
$data = array(
'name' => 'Killer Whale',
'email' => 'namnguyen2091#gmail.com',
'website' => 'baogiadientu.com'
);
// load and encode data
$json = new Zend_Json();
$encode = $json->encode($data);
echo $encode;
//decode with static function
echo '<pre>';
print_r(Zend_Json::decode($encode));
echo '</pre>';
But when I code like below, it doesn't work and I get an error:
Fatal error: Class 'Zend_Config_Writer_Xml' not found in D:\Programs\xampp\htdocs\baogiadientu\application\controllers\product.php on line 83
$this->zend->load('zend/config');
// create the config object
$config = new Zend_Config(array(), true);
$config->production = array();
$config->production->webhost = 'baogiadientu.com';
$config->production->database = array();
$config->production->database->params = array();
$config->production->database->params->host = 'localhost';
$config->production->database->params->username = 'root';
$config->production->database->params->password = '123456';
$config->production->database->params->dbname = 'baogiadientu';
$writer = new Zend_Config_Writer_Xml(); // **here**
echo $writer->toString($config);
I follow this article http://framework.zend.com/manual/2.0/en/modules/zend.config.writer.html. Please help me!
You are trying to do two things there (1) load and instantiate a Zend Config object and (2) do the same with Zend_Config_Writer_Xml - all without including the required files.
You may just need to require("Zend/Config.php") and require("Zend/Config/Writer/Xml.php") after ensuring they are inside your include_path
You are using a ZF1 library with the ZF2 documentation
Please check the correct documentation at their website:
http://framework.zend.com/manual/1.12/en/zend.config.writer.introduction.html

SoapClient + PHP + Sharepoint + Getting images from a list OR GetItemsByIds

I am using SoapClient to pull data out of a sharepoint list. If its a normal text field it works fine and gives me the image. I can even attach the image to the individual list elements and link it into another field and get the image that way. The problem with that is it asks me to log in to my sharepoint account whenever I access the page, which obviously a normal user of my site will not be able to do.
First, if there is a way around this, that will be a sufficient answer because that is my ideal way of doing it.
However, if the better way is to make a picture gallery and then pull the pictures from there then that isn't a problem.
Basically what I need to know is how to use the Imaging library and maybe the GetItemsByIds method? I am very new to soap and sharepoint in general so I appologize for what may be trivial questions but I really need to know how to do this and I can find no resource on the internet that explains what I need to know (if there is one, link it!). Keep in mind, I have to do this in PHP.
Here is some code that I use to pull the list data:
<?php
$authParams = array(
'login' => 'username',
'password' => 'pass'
);
$listName = "{GUID}";
$rowLimit = '500';
$wsdl = "list.wsdl";
$soapClient = new SoapClient($wsdl, $authParams);
$params = array(
'listName' => $listName,
'rowLimit' => $rowLimit;
);
echo file_get_contents($wsdl, FILE_TEXT, stream_context_create(array('http' => array('timeout' => 1))), 0, 1);
$rawXMLresponse = null;
try{
$rawXMLresponse = $soapClient->GetListItems($params)->GetListItemsResult->any;
}
catch(SoapFault $fault){
echo 'Fault code: '.$fault->faultcode;
echo 'Fault string: '.$fault->faultstring;
}
echo '<pre>' . $rawXMLresponse . '</pre>';
$dom = new DOMDocument();
$dom->loadXML($rawXMLresponse);
$results = $dom->getElementsByTagNameNS("#RowsetSchema", "*");
?>
//do the useful thing
<?php
unset($soapClient);
?>
It was an issue with the user permissions. Once we had an account with the correct permissions, it worked fine.

Categories