PHP Office 365 Graph authentication - php

I am having trouble authenticating and accessing the Microsoft Graph API via PHP.
I have the Azure app all setup with clientID and clientSecret codes, as well as the correct redirectURI.
When I try to view this PHP code in web browser, I get a HTTP 500 error.
I have the below code:
<?php
use Microsoft\Graph\Graph;
use Microsoft\Graph\Model;
$clientSecret = 'SAMPLE';
$clientId = 'SAMPLE';
$redirectUri = 'SAMPLE';
$tenantId = 'SAMPLE';
$guzzle = new \GuzzleHttp\Client();
$url = 'https://login.microsoftonline.com/' . $tenantId . '/oauth2/token?api-version=1.0';
$token = json_decode($guzzle->post($url, [
'form_params' => [
'client_id' => $clientId,
'client_secret' => $clientSecret,
'resource' => 'https://graph.microsoft.com/',
'grant_type' => 'client_credentials',
],
])->getBody()->getContents());
$accessToken = $token->access_token;
$graph = new Graph();
$graph->setAccessToken($accessToken);
$user = $graph->createRequest("GET", "/me")
->setReturnType(Model\User::class)
->execute();
echo "<script type='text/javascript'>alert('$user->getGivenName()');</script>";
?>
I am hoping someone can provide anything useful, as I can't seem to find documentation anywhere on this.
I have also had to install composer.phar on web hosting via SSH, and am not sure if that is running correctly / in the correct directory. It does have all the required add-ins installed though such as guzzleHTTP, Microsoft Graph, and oauth2.

Related

Generating a AWS Signature (ShipLogic)

So I'm implementing ship-logic's API into my program and have never worked with AWS authentication.
Did my research on the documentation and done the following:
<?php
$host = "api.shiplogic.com";
$accessKey = '******';
$secretKey = '******';
$requestUrl = 'https://api.shiplogic.com';
$uri = '/rates';
$httpRequestMethod = 'POST';
$data = '{"collection_address": {"company": "Kenesis Test","street_address": " 32 Goud Street, Goedeburg, Benoni","local_area": "Benoni","city": "Johannesburg","country": "ZA","code": "1501"},"delivery_address": {"street_address": "17 bloomberg street","local_area": "minnebron","city": "brakpan","code": "1541"},"parcels": [{"submitted_length_cm": 1,"submitted_width_cm": 1,"submitted_height_cm": 1,"submitted_weight_kg": 0.1}],"declared_value": 99}';;
require 'vendor/autoload.php';
use Aws\Signature\SignatureV4;
use Aws\Credentials\Credentials;
use GuzzleHttp\Client;
use GuzzleHttp\Psr7\Request;
use Psr\Http\Client\ClientInterface;
$signature = new SignatureV4('execute-api', 'af-south-1');
$credentials = new Credentials($accessKeyId, $secretAccessKey);
$psr7Request = new Request($httpRequestMethod, $requestUrl.$uri, ["content-type"=>"application/json"], $data);
$client = new Client([$requestUrl, 'timeout' => 30]);
$sr = $signature->signRequest($psr7Request, $credentials);
$response = $client->send($sr);
//var_dump($response);
?>
Now its a simple piece of code but I'm constantly getting a 403 response.
When I do the exact same request with PostMan, the response came back successfully.
Can any AWS guru assist me and point out if I am doing anything wrong??
Assistance would be highly appreciated.
P.S, I'm using sandbox credentials here, no worries.
It's a headers issue. You need to include the following headers when sending the request through.
$amzDate = date('Ymd\THis\Z');
$headers = [
'X-Amz-Date' => $amzDate,
'Cookie' => 'XDEBUG_SESSION=PHPSTORM',
'Content-Type' => 'application/json',
];
There is an error in your variable names.
$credentials = new Credentials($accessKeyId, $secretAccessKey);
should be
$credentials = new Credentials($accessKey, $secretKey);
Once you fix those the code works 100%.

Microsoft OneDrive SDK run as cron

Hi am using this OneDrive SDK . https://github.com/krizalys/onedrive-php-sdk . I am using PHP. What I need is to create a cronjob that will fetch my files in OneDrive and save it to my local directory. It works fine following the tutorial in the SDK. However, the way that SDK works is it needs you to be redirected to Microsoft account login page to be authenticated.
This will require a browser. My question, is it possible to do this by just running it in the backend like a cron? I can't seem to find a way to do it using the SDK. In Google, they will provide you a key to access the services without logging in every time. I am not sure about OneDrive.
$localPath = __DIR__.'/uploads/';
$today = date('Y-m-d');
$folder = $client->getMyDrive()->getDriveItemByPath('/'.$today);
echo "<pre>";
try {
$files = $folder->getChildren();
$createdDirectory = $localPath.$today;
// Check if directory exist
if(is_dir($createdDirectory)){
echo "\n"." Directory ".$createdDirectory." already exists, creating a new one..";
// Create new directory
$uuid1 = Uuid::uuid1();
$createdDirectory = $createdDirectory.$uuid1->toString();
echo "\n".$createdDirectory." created..";
}
// Create directory
mkdir($createdDirectory);
echo "\n".count($files)." found for ".$today;
// Loop thru files inside the folder
foreach ($files as $file){
$save = $file->download();
// Write file to directory
$fp = fopen($createdDirectory.'/'.$file->name, 'w');
fwrite($fp, $save);
echo("\n File ".$file->name." saved!");
}
} catch (Exception $e){
die("\n".$e->getMessage());
}
die("\n Process Complete!");
My code is something like that in the redirect.php
It doesn't look like that SDK supports the Client Credentials OAuth Grant. Without that, the answer is no. You may want to look at the official Microsoft Graph SDK for PHP which supports this via the Guzzle HTTP client:
$guzzle = new \GuzzleHttp\Client();
$url = 'https://login.microsoftonline.com/' . $tenantId . '/oauth2/token?api-version=1.0';
$token = json_decode($guzzle->post($url, [
'form_params' => [
'client_id' => $clientId,
'client_secret' => $clientSecret,
'resource' => 'https://graph.microsoft.com/',
'grant_type' => 'client_credentials',
],
])->getBody()->getContents());
$accessToken = $token->access_token;

"unable to get local issuer certificate" when trying to access Microsoft Graph

I want to configure my Symfony4 application to read and send e-mails using the msgraph-sdk-php library.
My first experience was this piece of code:
$guzzle = new \GuzzleHttp\Client();
$url = 'https://login.microsoftonline.com/' . $tenantId . '/oauth2/token?api-version=1.0';
$token = json_decode($guzzle->post($url, [
'form_params' => [
'client_id' => $clientId,
'client_secret' => $clientSecret,
'resource' => 'https://graph.microsoft.com/',
'grant_type' => 'client_credentials',
],
'verify' => false
])->getBody()->getContents());
$accessToken = $token->access_token;
$graph = new Graph();
$graph->setAccessToken($accessToken);
try {
$user = $graph->createRequest("GET", "/me")
->setReturnType(User::class)
->execute();
} catch (GraphException $e) {
$user=(object) ['getGivenName'=>$e->getMessage()];
}
return "Hello, I am $user->getGivenName() ";
But then Symfony shows me an exception page with this message:
cURL error 60: SSL certificate problem: unable to get local issuer certificate
What should I do to overcome this?
On Windows systems cURL can't access the CA-Certs sometimes. So you have to download the CA-Files and add them to Curl. You can download the certificate here:
http://curl.haxx.se/docs/caextract.html
curl_setopt($ch, CURLOPT_CAINFO, __DIR__ . "/certs/cacert.pem");
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, true);
So to fix the problem temporary you can disable the Peer verification but you should do that only for testing.
$client->setDefaultOption('verify', false);
Then it should be possible to connect. To add the certificate you can to the following but then you have to download the certificate first.
$client = new \GuzzleHttp\Client();
$client->setDefaultOption('verify', 'curl-ca-bundle.crt');
Or last solution ad the ca file to your php.ini (The file from curl.haxx.se):
curl.cainfo = "[pathtothisfile]\cacert.pem"

Oauth 1.0 - Connection to an Api

I am trying to make a connection to an API that will provide my website with information about cars and other stuff. The problem is that I can connect with it from PostMan because it generates a signature and a nounce.
The problem that I am suffering is that when I want to connect throw PHP the OAUTH class is not generating the nounce and the signature so I can´y connect.
I have also tried with CURL and anything better happened.
My current code is this:
$config = array(
'consumer_key' => 'XXXXXXXXXXXXXXXXXXXXXXX',
'consumer_secret' => 'XXXXXXXXXXXXXXXXXXXXXXX',
'request_uri' => 'http://bdc.autobild.es/autobild'
);
$oauth = new OAuth($config['consumer_key'],
$config['consumer_secret'], OAUTH_SIG_METHOD_HMACSHA1);
$requestTokenInfo = $oauth->getRequestToken('http://bdc.autobild.es/autobild/','http://localhost/myfolder/');
d($requestTokenInfo);
$accessTokenInfo = $oauth->getAccessToken('http://bdc.autobild.es/autobild/');
d($accessTokenInfo);
$requestInfo = $oauth->getLastResponseInfo();
d($requestInfo);
$oauth->fetch("http://bdc.autobild.es/autobild/list?type=coche");
$data = $oauth->getLastResponseInfo();
d($data);
Thanks!
Here's how I authenticate to an OAuth service, maybe it will be useful:
signin.php
//Gets the request token
session_start();
$oauth = new OAuth($config['consumer_key'], $config['consumer_secret'], OAUTH_SIG_METHOD_HMACSHA1, OAUTH_AUTH_TYPE_FORM);
$requestTokenInfo = $oauth->getRequestToken("<oauth token URL>", $_SERVER["SERVER_NAME"]."/callback.php");
$_SESSION["tokenInfo"] = $requestTokenInfo;
header("Location: <oauth authorize URL>?token='.$requestTokenInfo["oauth_token"]); //May vary on your OAuth service
In callback.php
session_start();
$oauth = new OAuth($config['consumer_key'], $config['consumer_secret'], OAUTH_SIG_METHOD_HMACSHA1, OAUTH_AUTH_TYPE_FORM);
$oauth->setToken($_REQUEST['oauth_token'], $_SESSION["tokenInfo"]["secret"]);
$accessTokenInfo = $oauth->getAccessToken("<oauth authorize URL>");
$_SESSION["accessToken"] = $accessTokenInfo;
unset($_SESSION["tokenInfo"]); //Its work is done
Now whenever I need to get some API data:
session_start();
$oauth = new OAuth($config["consumer_key"], $config["consumer_secret"], OAUTH_SIG_METHOD_HMACSHA1, OAUTH_AUTH_TYPE_URI);
$oauth->setToken($_SESSION["accessToken"]["token"],$_SESSION["accessToken"]["secret"]);
$oauth->fetch("URL");
$data = $oauth->getLastResponse();
$requestInfo = $oauth->getLastResponseInfo();
$responseHeaders = $oauth->getLastResponseHeaders();
This will work in the cases you need to perform requests on behalf of a user. The user will be redirected to the service's oauth autorizer and then returned to the callback page with their tokens if they authorize your app.
If the service has provided some methods which are accessible from your app directly (typically getting app usage information and the like is linked to these) then you can probably skip a big portion of this:
$oauth = new OAuth($config['consumer_key'], $config['consumer_secret'], OAUTH_SIG_METHOD_HMACSHA1);
$oauth->fetch(url);
I have found the solution. The problem was that an argument was missing here:
$oauth = new OAuth($config['consumer_key'], $config['consumer_secret'], OAUTH_SIG_METHOD_HMACSHA1);
The correct way is:
$oauth = new OAuth($config['consumer_key'], $config['consumer_secret'], OAUTH_SIG_METHOD_HMACSHA1, OAUTH_AUTH_TYPE_URI);
So, the complete code is like this:
$config = array(
'consumer_key' => 'XXXXXXXXXXXXXXXXXXXXXXXX',
'consumer_secret' => 'XXXXXXXXXXXXXXXXXXXXXXXX',
);
$oauth = new OAuth($config['consumer_key'], $config['consumer_secret'], OAUTH_SIG_METHOD_HMACSHA1, OAUTH_AUTH_TYPE_URI);
$requestInfo = $oauth->getLastResponseInfo();
$oauth->fetch("http://example.es/list?type=car");
$data = $oauth->getLastResponse();
var_dump($data);
Thank´s everyone for the help!
You can use another library, i recommand you tu use GuzzleHttp.
To install it you can use Composer .
{
"require": {
"guzzlehttp/guzzle": "6.5",
"guzzlehttp/oauth-subscriber": "^0.6.0"
} }
And for implementation you can process like this
use \GuzzleHttp\Client;
use \GuzzleHttp\HandlerStack;
use \GuzzleHttp\Subscriber\Oauth\Oauth1;
$stack = HandlerStack::create();
$middleware = new Oauth1(['consumer_key' => '','consumer_secret' => '','signature_method' => Oauth1::SIGNATURE_METHOD_HMAC]);
$stack->push($middleware);
$client = new Client(['base_uri' => '<BASE_URL>','handler' => $stack]);
$res = $client->get('<ROUTE_DATA>', ['auth' => 'oauth'])->getBody()->getContents();
$res = json_decode($res);
var_dump($res->title);

evernote developer api user login and insert note

<?php
require './vendor/autoload.php';
$client = new Evernote\Client(array(
'consumerKey' => 'xxxx',
'consumerSecret' => 'xxxxx'
));
$requestToken = $client->getRequestToken('index.html');
$authorizeUrl = $client->getAuthorizeUrl($requestToken['oauth_token']);
$accessToken = $client->getAccessToken(
$requestToken['oauth_token'],
$requestToken['oauth_token_secret'],
$_GET['oauth_verifier']
);
$token = $accessToken['oauth_token'];
$client = EvernoteClient($token=$token);
$client = new Evernote\Client(array('token' => $token));
$noteStore=$client->getNoteStore();
$note = $Types->Note();
$note->title="I'm a test note!";
$note->content = '<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE en-note SYSTEM "http://xml.evernote.com/pub/enml2.dtd">';
$note->content += '<en-note>Hello, world!</en-note>';
$note = $noteStore->createNote($note);
?>
I iam trying to login to user account and add note to there account.But i an not able to understand what is wrong.Can any one give code for my implementation .Thank you.
Not sure what error you got only from this code but Client->getRequestToken requires full callback URL (http://yourdomain/path) instead of just a file name.
You can see how it works here. Especially, function.php might help.

Categories