Generating a AWS Signature (ShipLogic) - php

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%.

Related

PHP Office 365 Graph authentication

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.

How to send a correct authorization header for basic authentication using guzzle

How to send a correct authorization header for basic authentication using guzzle
use GuzzleHttp\Client;
$username='EFDEMO';
$password='EFDEMO';
$client = new Client(['auth' => [$username, $password]]);
$res = $client->request('GET', 'https://mb-
rewards.calusastorefront.p2motivate.com/client/json.php/
getMemberAccount');
$res->getStatusCode();
$response = $res->getBody();
echo $response;
the error I am getting
{"statusCode":"Error","error":
{"errorCode":"400","errorMessage":"Authentication Header ID field must
match Basic Authentication Username"}}
Referring to documentation you should pass the auth parameter in request method instead of client's constructor:
$client = new Client();
$res = $client->request(
'GET',
'past-url-here',
['auth' => [$username, $password]]
);
I solved it like below
<?php
require '../x_static_libs/guzzle/vendor/autoload.php';
use GuzzleHttp\Client;
$client = new Client();
$username = 'xxxxxx';
$password = 'xxxxxxxx';
$token = 'xxxxxxxxxxxxxxxxxxxx';
$url = 'https://ervb-rewards.com/client/json.php';
$api_token =
base64_encode(json_encode(['id'=>'xxxxxxx','token'=>'xxxxxxxxxxxxxxxxxxxxxx']));
$res = $client->request(
'GET',
$url.'/getMemberAccount',
['auth' => [$username,$api_token]]
);
$jsonData = json_decode($res->getBody(), true);
echo "<pre>";
print_r($jsonData);
echo "</pre>";

How to send a message to specific connectionId to aws api gateway websockets?

I am using this code to establish a new connection on user device.
var socket = new WebSocket("wss://cdsbxtx2xi.execute-api.us-east-2.amazonaws.com/test");
socket.onmessage = function (event) {
json = JSON.parse(event.data);
connectionId = json.connectionId;
document.cookie = "connection_id="+connectionId;
console.info(json);
}
Suppose from this request I get connectionId CLO5bFP1CYcFSbw=
Another user from another device also established a new connection with connectionId Cs42Fs5s5yuSbc=. Now how can I send a message from user 2 device to user 1?
I already tried this. I don't know this is right way or not but still, i am open for any suggestion.
use Aws\Signature\SignatureV4;
use GuzzleHttp\Client;
use GuzzleHttp\Psr7\Request;
use Aws\Credentials\Credentials;
$client = new GuzzleHttp\Client();
$credentials = new Credentials("XXXXXXXXXX","XXXXXXXX");
$url = "https://cdsbxtx2xi.execute-api.us-east-2.amazonaws.com/test/#connections/CLO5bFP1CYcFSbw=";
$region = 'us-east-2';
$msg['action'] = 'sendmessage';
$msg['data'] = 'hello world';
$msg = json_encode($msg);
$request = new Request('POST', $url, '["json"=>$msg]');
$s4 = new SignatureV4("execute-api", $region);
$signedrequest = $s4->signRequest($request, $credentials);
$response = $client->send($signedrequest);
echo $response->getBody();
This code keeps on loading and finally throws gateway timeout error.
I expect that user 2 should be able to send message to any specific connectionId over wss or https.
I tried https by signing this request but signing doesn't works. I am getting an error with the signing part
After struggling with this problem for the last 3 days finally I found the solution. None of the previously mentioned solutions on StackOverflow was working for me.
This is the correct solution. I hope this will be helpful to someone.
use Aws\Signature\SignatureV4;
use GuzzleHttp\Client;
use GuzzleHttp\Psr7\Request;
use Aws\Credentials\Credentials;
$client = new GuzzleHttp\Client();
$credentials = new Credentials(accessKeyId, secretAccessKey);
$url = "https://xsdsdsd.execute-api.us-east-2.amazonaws.com/test/#connections/CNtBveH2iYcCKrA=";
// CNtBveH2iYcCKrA= is connectionid
$region = 'us-east-2';
$msg['action'] = 'sendmessage';
$msg['data'] = 'hello world';
$msg = json_encode($msg);
$headers = array('Content-Type => application/x-www-form-urlencoded');
$request = new GuzzleHttp\Psr7\Request('POST', $url, ['Content-Type' => 'application/json'], $msg);
$signer = new Aws\Signature\SignatureV4('execute-api', $region);
$request = $signer->signRequest($request, $credentials);
$headers = array('Content-Type => application/x-www-form-urlencoded');
$client = new \GuzzleHttp\Client([ 'headers' => $headers]);
$response = $client->send($request);
$result = $response->getBody();
Hey you can use the Connection URL to send message also.
Connection url : https://{api-id}.execute-api.us-east-1.amazonaws.com/{stage}/#connections
To find go to : Aws console > Api gateway > api > your_api > dashboard their you will find your connection url.
Use php cURL method because its easy and fast as compare to GuzzleHttp
$curl = curl_init();
curl_setopt_array($curl, array(
CURLOPT_URL => 'https://{api-id}.execute-api.us-east-1.amazonaws.com/{stage}/#connections/{YOUR_CONNECTION_ID_OF_USER}',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => '',
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 0,
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_POSTFIELDS =>'{"message" : "Hello world"}',
CURLOPT_HTTPHEADER => array(
'Content-Type: application/json'
),
));
$response = curl_exec($curl);
curl_close($curl);
echo $response;

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