I am having issues setting up the "One-Click-App" oAuth on Bigcommerce with the BC PHP API library.
The issue at the moment is getting the actual auth token. I've tried various methods and believe it's down to the (Code/Context/Scope) get requests. They return as null every time.
I've tried both:
$request->query('code');
$request->get('code');
On the BC app launch screen I am presented with:
Trying to get property 'access_token' of non-object
Which of course is because the token is returning null.
Here is my controller in Laravel
namespace App\Http\Controllers;
use \Illuminate\Http\Request;
use Bigcommerce\Api\Client as Bigcommerce;
class BController extends Controller
{
//
public function index(Request $request)
{
$object = new \stdClass();
$object->client_id = 'xxxxxxxxxxxxxx';
$object->client_secret = 'xxxxxxxxxxxxxxxx';
$object->redirect_uri = 'https://linkto/process_oauth_result';
$object->code = $request->query('code');
$object->context = $request->query('context');
$object->scope = $request->query('scope');
Bigcommerce::useJson();
$authTokenResponse = Bigcommerce::getAuthToken($object);
// configure BC App
Bigcommerce::configure([
'client_id' => env('xxxxxxxxxxxxxx'),
'auth_token' => $authTokenResponse->access_token,
'store_hash' => 'xxxxxxx'
]);
Bigcommerce::verifyPeer(false);
return 'Success!';
}
}
Well it turns out that this works fine. I am using Runcloud to manage the app and the click-jacking option was blocking the iframe on the app screen!
Related
I'd like to authenticate our application user against Firebase/Firestore and then make a request to the storage as this user (i.e. not as the service account).
I know of two methods for the authentication:
Simple HTTP Request
$client = new GuzzleHttp\Client();
$responee = $client->request(
'POST',
'https://www.googleapis.com/identitytoolkit/v3/relyingparty/verifyPassword?key=' . $key,
[
'headers' => [
'content-type' => 'application/json',
'Accept' => 'application/json'
],
'body' => json_encode([
'email' => $email,
'password' => $password,
'returnSecureToken' => true
]),
'exceptions' => false
]
);
Kreait SDK
$userRecord = $auth->verifyPassword($email, $password);
What I don't know is how to use this information to make a request to the storage.
Google Cloud Firestore SDK
StorageClient accepts a config key credentialsFetcher but I don't know how to use it. It accepts any object that implements FetchAuthTokenInterface. I've toyed with those that exist, even tried implementing my own that just passes on the idToken from the Simple HTTP Request method. No luck.
$credentialsFetcher = new myFetchAuthTokenImplementation($idToken);
$storage = new StorageClient([
'credentialsFetcher' => $credentialsFetcher,
]);
$bucket = $storage->bucket('my_bucket');
$object = $bucket->object('file_backup.txt');
print $object->downloadAsString();
use Google\Auth\FetchAuthTokenInterface;
class myFetchAuthTokenImplementation implements FetchAuthTokenInterface
{
private $token;
public function __construct(string $token)
{
$this->token = [
'access_token' => $token,
];
}
public function fetchAuthToken(callable $httpHandler = null)
{
return $this->token;
}
public function getCacheKey()
{
return null;
}
public function getLastReceivedToken()
{
return $this->token;
}
}
Kreait SDK
It seems it can fetch information from storage but only using the service account. Not my application user.
$firebaseFactory = (new Factory)->withServiceAccount(__DIR__.'/google-service-account.json');
$storage = $firebaseFactory->createStorage();
$imageUrl = $storage->getBucket()
->object('file_backup.txt')
I would need to re-initialize the $firebaseFactory with the application user record, something like this fictitious method $firebaseFactory = (new Factory)->withApplicationUser($userRecord);
Although I would like to use some SDK, any solution is fine, even with simple HTTP requests.
I would probably be able to implement this using the Google JavaScript SDK but I'd like to stick to PHP.
Your help is greatly appreciated.
As far as I know, the Kreait PHP SDK wraps the Google Cloud Storage REST API. If it does, it always accesses Storage with Administrative credentials, and there is no way to access it as a Firebase Authentication user account, nor to enforce the security rules for a specific user.
To access Cloud Storage as a Firebase Authentication user, you will have to authenticate client-side, and pass the resulting ID token to an SDK/API that enforces Firebase security rules for specific users. This means you'll have to use one of the client-side Firebase SDKs for accessing Cloud Storage, as there currently is no public REST API that exposes this functionality.
I'm integrating Laravel with GoCardless to allow my users to take card payments however I'm struggling installing the GoCardless php wrapper.
I've followed the following doc:
https://developer.gocardless.com/getting-started/partners/building-an-authorisation-link/
It says to use the following, am I right in saying this will go in my controller? surely with Laravel I wouldnt need to require the vendor/autoload?
<?php
require 'vendor/autoload.php';
// You should store your client ID and secret in environment variables rather than
// committing them with your code
$client = new OAuth2\Client(getenv('GOCARDLESS_CLIENT_ID'), getenv('GOCARDLESS_CLIENT_SECRET'));
$authorizeUrl = $client->getAuthenticationUrl(
// Once you go live, this should be set to https://connect.gocardless.com. You'll also
// need to create a live app and update your client ID and secret.
'https://connect-sandbox.gocardless.com/oauth/authorize',
'https://acme.enterprises/redirect',
['scope' => 'read_write', 'initial_view' => 'login']
);
// You'll now want to direct your user to the URL - you could redirect them or display it
// as a link on the page
header("Location: " . $authorizeUrl);
Apologies, if someone can point me in the right direction I would appreciate.
My controller currently looks like.
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Http\Requests;
class goCardlessController extends Controller
{
public function index()
{
$client = new OAuth2\Client(env('GOCARDLESS_CLIENT_ID'), env('GOCARDLESS_CLIENT_SECRET'));
$authorizeUrl = $client->getAuthenticationUrl(
'https://connect-sandbox.gocardless.com/oauth/authorize',
'REDIRECT_URL',
['scope' => 'read_write', 'initial_view' => 'login']
);
header("Location: " . $authorizeUrl);
}
}
but I get the error:
Class 'App\Http\Controllers\OAuth2\Client' not found
Which makes sense because I haven't defined it in my controller but Im wondering how I would do this?
Try this in your controller:
use Oauth2;
Or alternatively, $client = new \OAuth2\Client(.... Do note the \ before Oauth2
How to set it up I read the tutorial http://code.tutsplus.com/tutorials/working-with-restful-services-in-codeigniter-2--net-8814. But I am unable to get the idea, I want more details. I am very new to CodeIgniter and to API.
I did the following steps from nettuts article
download both restclient and restserver and curl
I try to run examples from rest-server it does not show anything to me. I load my own controller and methods
REST SERVER :
this is the server that listen to client (restClient) request.
RESTServer has the Request methods :
POST()
GET()
PUT()
DELETE()
and these are use like index_put(); keep in mind when you called it from RESTClient ,you will called it like :
$this->index();
not
$this->index_put(); //because restserver it self recognize the nature of request through header.
Here is a simple example:
RESTClient:
function request_test() {
$this->load->library('rest', array(
'server' => 'http://restserver.com/customapi/api/',
//when not use keys delete these two liness below
'api_key' => 'b35f83d49cf0585c6a104476b9dc3694eee1ec4e',
'api_name' => 'X-API-KEY',
));
$created_key = $this->rest->post('clientRequest', array(
'id' => '1',
'CustomerId' => '1',
'amount' => '2450',
'operatorName' => 'Jondoe',
), 'json');
print_r($created_key);
die;
}
Make sure you loaded rest library.
RESTSERVER:
<?php
require APPPATH . '/libraries/REST_Controller.php';
class api extends REST_Controller {
public function clientRequest_post() {
//to get header
$headers=array();
foreach (getallheaders() as $name => $value) {
$headers[$name] = $value;
}
//to get post data
$entityBody = file_get_contents('php://input', 'r');
parse_str($entityBody , $post_data);
//giving response back to client
$this->response('success', 200);
}
}
configuration config/Rest.php:
//if you need no authentication see it's different option in the same file
$config['rest_auth'] = false;
//for enabling/disabling API_KEYS
$config['rest_enable_keys'] = FALSE;
I have already written an application in a procedural way and am trying to move into into a Laravel framework. I'm having trouble with the SOAP exchange section as I am getting an ID value that authenticates the user but cannot access that value (as a cookie) later in the program to authenticate the search.
Here is my code so far:
<?php namespace App;
use Artisaninweb\SoapWrapper\Facades\SoapWrapper;
use Illuminate\Http\RedirectResponse;
class SoapController {
private $auth_response;
private $cookie;
private $search_client;
private $search_response;
public function soapExchange() {
// create SOAP client and add service details
SoapWrapper::add(function ($service) {
$service
->name('WoSAuthenticate')
->wsdl('http://search.webofknowledge.com/esti/wokmws/ws/WOKMWSAuthenticate?wsdl')
->trace(true)
->cache(WSDL_CACHE_NONE);
});
SoapWrapper::service('WoSAuthenticate', function($service) {
// call authenticate() method to get SID cookie
$auth_response = $service->call('authenticate', []);
$cookie = $auth_response->return;
// test for cookie return
// print($cookie);
});
// create SOAP client and add service details
$search_client = new SoapWrapper;
$search_client::add(function ($service) {
$service
->name('WoSSearch')
->wsdl('http://search.webofknowledge.com/esti/wokmws/ws/WokSearch?wsdl')
->trace(true)
->cache(WSDL_CACHE_NONE);
});
if (isset($auth_response->return)) {
// if there is an SID returned then add it to the cookie attribute of the search client
$search_client->__setCookie('SID', $cookie);
} else {
// route to relevant view to display throttle error
return redirect('throttle');
}
}
}
I am successfully retrieving the response from the Web API call and getting a code to authenticate the user, saved as $cookie. However, I need then to create another SoapWrapper for performing the search and this needs the ID code attached by using the __setCookie method. If nothing is returned by the authenticate call then it redirects to an error message via throttle.blade.php elsewhere.
Surely there is a way to return a value created from a function so that it can be used elsewhere?
** EDIT **
Looked into employing SoapClient instead and including all operations within a single function. It all relates to a specific Web API anyway so I guess separation of concerns is not so much of an issue. FYI the new class I am trying is this:
<?php namespace App\Models;
use SoapClient;
use Illuminate\Http\RedirectResponse;
class SoapWrapper {
public function soapExchange() {
// set WSDL for authentication and create new SOAP client
$auth_url = "http://search.webofknowledge.com/esti/wokmws/ws/WOKMWSAuthenticate?wsdl";
// array options are temporary and used to track request & response data
$auth_client = #new SoapClient($auth_url);
// set WSDL for search and create new SOAP client
$search_url = "http://search.webofknowledge.com/esti/wokmws/ws/WokSearch?wsdl";
// array options are temporary and used to track request & response data
$search_client = #new SoapClient($search_url);
// run 'authenticate' method and store as variable
$auth_response = $auth_client->authenticate();
// call 'setCookie' method on '$search_client' storing SID (Session ID) as the response (value) given from the 'authenticate' method
// check if an SID has been set, if not it means Throttle server has stopped the query, therefore display error message
if (isset($auth_response->return)) {
$search_client->__setCookie('SID',$auth_response->return);
} else {
return Redirect::route('throttle');
}
}
}
Maybe try $GLOBALS?
<?php
$GLOBALS[data] = "something";
function abc(){
echo $GLOBALS[data];
}
?>
use Artisaninweb\SoapWrapper\Facades\SoapWrapper;
class SoapController extends Controller {
public $resultSoapStatus;
public $resultSoapAuthority;
public function heySoap{
SoapWrapper::add(function ($service) ...
$data = [
'MerchantID' => $MerchantID,
'Amount' => $Amount,
'Description' => $Description,
'Email' => $Email,
'Mobile' => $Mobile,
'CallbackURL' => $CallbackURL
];
SoapWrapper::service('test', function ($service) use ($data) {
$resultSoap = $service->call('PaymentRequest', [$data]);
$this->resultSoapStatus = $resultSoap->Status;
$this->resultSoapAuthority = $resultSoap->Authority;
});
if($this->resultSoapStatus == 100 && strlen($this->resultSoapAuthority) == 36)
{
//Do Something
}
else
{
return Redirect::back();
}
}
}
Enjoy bro
I have two cakePHP apps on 2 different servers. One app is required to get data from the first one; I have succeeded to put the Restful architecture in place but I failed to implement an authentication procedure to the requests the server sends. I need to authenticate to secure the data. I have looked around on the web but can't seem to get it working. Can anyone point me to a resource / tutorial that explains this in detail.
What I would ultimately need would be a way to authenticate my server every time it sends a request to the other server. Any help would be appreciated.
I finally got it to work after some research; indeed one of the solutions is OAuth. In case you are facing the same problem, I can advise you this Plugin made for CakePHP.
In details what I did was put the OAuth Plugin into my API Server and I used it like so for my restful controller:
class RestObjectController extends AppController {
public $components = array('RequestHandler', 'OAuth.OAuth');
public $layout = FALSE;
public function token() {
$this->autoRender = false;
try {
$this->OAuth->grantAccessToken();
} catch (OAuth2ServerException $e) {
$e->sendHttpResponse();
}
}
public function index() {
$objects = $this->Object->find('all');
$this->set(array(
'objects' => $objects,
'_serialize' => array('objects')
));
}
The function RestObject.token() is what I would call to get an Access token which will be used to give me access to the Resources in my controller. (Note that by declaring OAuth in my controller components, all the resources within my controller will need an access token to be accessible).
So on the client Server I would get an access token in the following way:
public function acquireAccessToken(){
$this->autoRender = FALSE;
App::uses('HttpSocket', 'Network/Http');
$link = API_SERVER."rest_objects/token";
$data = array(
'grant_type' => 'client_credentials',
'client_id' => 'xxxx',
'client_secret' => 'xxxx'
);
$response = $httpSocket->post($link, $data);
if($response->code == 200){
$data = json_decode($response->body, true);
return $data['access_token'];
}
return FALSE;
}
This assumes that you have clients already set up as explained in the Plugin Doc (replace xxxx by the real values for the client credentials). Once I have my access token, all I have to do is use it as follows:
public function test(){
$this->layout = FALSE;
App::uses('HttpSocket', 'Network/Http');
$httpSocket = new HttpSocket();
if($access_token = $this->acquireAccessToken()){
$link = API_SERVER."rest_objects.json"; //For the index as e.g.
$data = array('access_token' => $access_token);
$response = $httpSocket->get($link, $data);
}
}
And here you have it! So start by reading the Oauth Specification to understand the Protocol (in particular the Obtaining Authorization part), see which protocol (can be different from the one I used) applies and adapt to your case by using the Plugin
Tutorial Here