How to use Woocommerce Api's using JWT token in Laravel? - wordpress

I am using Woocommerce for getting data in Laravel. I am using the package:
https://github.com/woocommerce/wc-api-php
Now I am using consumer key and consumer secret for getting data. But now requirement has been change. Now i want to get API's data using JWT Auth token. This time I am creating object as,
$this->client = new Client(
Cookie::get('site_url'),
Cookie::get('key'),
Cookie::get('secret'),
[
'timeout' => 120,
'version' => config('woocommerce.api_version'),
]
);
And then call method to get, post, etc.
$this->client->get($endpoint, $parameters);
But I want to pass the JWT token to get data.

Related

WooCommerce REST API: Gateway does not support admin changing the payment method on a Subscription

I am using WooCommerce Subscription REST API to extend the subscription of the user. The problem that I have is that when I want to update expire time I get this error:
Gateway does not support admin changing the payment method on a Subscription
Does someone know where is the problem?
I am using the following code to update the subscription expire time:
return $this->guzzleClient->request('PUT', 'wp-json/wc/v1/subscriptions/'.$id, [
'json' => [
'end_date' => $endDate->toDateTimeString(),
'status' => 'active',
]
]);
We ran into a similar issue. Instead of passing the whole subscription object back, we instead only passed the necessary information (in our case we wanted to add to the coupon_lines field).
Our resulting payload looked like:
{
coupon_lines: [
{
code: "sample-code",
amount: "10.00"
}
]
}

JWT key for mercure

I try generate JWT key for Mercure settings
I use this manual
https://medium.com/#stefan.poeltl/instant-realtime-notifications-with-symfony-and-mercure-e45270f7c8a5
for pass myJWTKey JWT is
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJtZXJjdXJlIjp7InN1YnNjcmliZSI6W10sInB1Ymxpc2giOlsiKiJdfX0.iTVjHoLv9bB-O5RNnTtzOFxIW-YECk2JXZeMekZ4GwA
I found a token builder ( Signed JSON Web Token )
http://jwtbuilder.jamiekurtz.com/
but I find no setting that generates a correct JWT. How do I do it? What I miss?
I tried generate token for env settings
MERCURE_PUBLISH_URL=http://mercure.dev:3000/.well-known/mercure
# The default token is signed with the secret key: !ChangeMe!
MERCURE_JWT_TOKEN=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJtZXJjdXJlIjp7InN1YnNjcmliZSI6W10sInB1Ymxpc2giOlsiKiJdfX0.iTVjHoLv9bB-O5RNnTtzOFxIW-YECk2JXZeMekZ4GwA
###< symfony/mercure-bundle ###
This token is for default password in docker-compose
mercure:
image: dunglas/mercure
environment:
# You should definitely change all these values in production
- JWT_KEY=myJWTKey
- DEMO=1
- ALLOW_ANONYMOUS=1
- HEARTBEAT_INTERVAL=30s
- ADDR=:3000
if I change myJWTKey to mysecure pass - how I can generate token?
Just an addition to a great answer by #Daidon. Mercure bundle uses lcobucci/jwt and registers it's factory as a service.
If you want to generate JWT do the following
Pass the factory as an argument with #mercure.hub.default.jwt.factory (here default is for your hub name)
In your service/controller
public function generateJwt(LcobucciFactory $factory): string
{
return $factory->create(['*']);
}
UPD: even easier way to get a JWT token
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Mercure\Authorization;
public function generateJwt(Request $request, Authorization $authorization): string
{
return $authorization->createCookie($request, ['*'])->getValue();
}
You can use different libraries for doing that, a very simple and fast one would be php-jwt
Then do
composer require firebase/php-jwt
And in the code you can do then:
use \Firebase\JWT\JWT;
$key = "12345678";
$payload = [
'mercure' => [
'publish' => ['*'],
],
];
$jwt = JWT::encode($payload, $key); // holds valid jwt now
The library will automatically inject the headers that you need (default: alg HS256, typ: jwt) and set the payload for you. Then it encodes it to base64 and signs it also.
Go on and set a cookie with this jwt or use it in authorization header now :-)
If you want to use the JWT for subscriber authentication, don't forget to put the subscribe key in the payload.
$payload = [
'mercure' => [
'subscribe' => ['*'], // make this a list of concrete topics, don't use *
],
];
Also for that usecase, you can carry around some data in the cookie, by providing a payload key with an object:
$payload = [
'mercure' => [
'subscribe' => ['*'],
'payload' => [
'userId' => $user->getId()
]
],
];
Apologize for late answer, you can simply generate new jwt token once using the official page https://jwt.io/.

How to get Google refresh token with knpuniversity/oauth2-client-bundle?

I use knpuniversity/oauth2-client-bundle and league/oauth2-google to connect users in my Symfony 4 web app using a "Sign in with Google" feature. I followed this tuto. I registered my app in Google.
I set access_type: offline in the knpu.oauth2.client.google configuration (config/packages/knpu_oauth2_client.yaml file)
I try to get the user refresh token in my GoogleAuthenticator::getUser(League\OAuth2\Client\Token\AccessToken $credentials) method (which extends KnpU\OAuth2ClientBundle\Security\Authenticator\SocialAuthenticator).
Unfortunately, $credentials->getRefreshToken() always returns null.
Why don't I get the user refresh token ?
As per documentation, "Refresh tokens are only provided to applications which request offline access". So, when instantiating the provider you need to set the accessType.
use League\OAuth2\Client\Provider\Google;
$provider = new Google([
'clientId' => '{google-client-id}',
'clientSecret' => '{google-client-secret}',
'redirectUri' => 'https://example.com/callback-url',
'accessType' => 'offline',
]);
In knpu_oauth2_client configuration, you can do:
google:
type: google
client_id: '%env(OAUTH_GOOGLE_CLIENT_ID)%'
client_secret: '%env(OAUTH_GOOGLE_CLIENT_SECRET)%'
redirect_params: {}
access_type: offline

Using a single Cloudflare account in Wordpress with WP Super Cache with visible API key

We are starting to use Cloudflare on a few Wordpress client accounts and notice in the CDN settings that my email address and API key are visible to the client.
Is this a potential security issues where others can see my Cloudlflare email address and API key? Should I be using 1 Cloudflare account per client account?
Here is a screenshot (i have blurred the API key and deleted the email input box in the console) but both these values are visible to the customer.
What is the worse thing they could do with these 2 pieces of data?
you have to use tokens instead of global api key. you strict token to certain zone only
This only will NOT solve the problem, you have to manually modify wp fastest cache plugin to modify the request to match API tokens usage.
the requests can be found in inc\cdn.php
The modified file:
https://gist.github.com/ahmed-abdelazim/7c8170f7fc4e821c6b015d770fcbf14a
so
$header = array("method" => "DELETE",
'headers' => array(
"X-Auth-Email" => $email,
"X-Auth-Key" => $key,
"Content-Type" => "application/json"
),
"body" => '{"purge_everything":true}'
);
is converted to
$header = array("method" => "DELETE",
'headers' => array(
//"X-Auth-Email" => $email,
"Authorization" => "Bearer ".$key,
"Content-Type" => "application/json"
),
"body" => '{"purge_everything":true}'
);
and this occured five times in the plugin in the cdn.php file
simply creating API Token worked for me. There are some pre made template. There was for wordpress one as well. Just selected and created and added it to wp fastest cache and that worked.

Get current user inside register_rest_route method

How to retrive wp_get_current_user() inside a register_rest_route callback (Wordpress site)?
I'm just trying to do a simple hello wp_get_current_user()->user_login on a php test page:
add_action('rest_api_init', 'helloTest');
function helloTest() {
register_rest_route('hello', 'hello/(?P<id>\d+)', array(
'methods' => WP_REST_SERVER::READABLE,
'callback' => 'showHello'
));
}
function showHello($someVariable) {
echo "Hello " . wp_get_current_user()->user_login . $someVariable;
}
But wp_get_current_user() is null and wp_get_current_user->ID is 0;
I dont want to authenticate the user again. I just want to retrieve his username. If he is not logged in, just show empty an empty string.
If I have to authenticate again, how to add a "nonce" to it? On internet I just have examples using javascript, but not directly on PHP methods.
Issues in your code
First off, you should understand properly how to add custom WP REST API endpoints:
An endpoint's namespace (the first parameter passed to register_rest_route()) should be in this format: your-plugin/v<version>. E.g. hello/v1 or hello-world/v1 and not just hello or hello-world.
$someVariable (the first parameter passed to your endpoint callback function) is not just any variable — it's an instance of the WP_REST_Request class — and shouldn't be echo-ed like what you did here:
function showHello($someVariable) {
echo "Hello " . wp_get_current_user()->user_login . $someVariable;
}
And normally, the $someVariable is better be changed to $request (i.e. rename it to "request").
And you should return a valid WP REST API response. For example, to return just the username:
return new WP_REST_Response( wp_get_current_user()->user_login, 200 );
And know your own API endpoint URL..
(based on your original namespace)
/wp-json/hello/hello/1 <- correct
/wp-json/hello/?John <- incorrect
because in your code, the parameter is a number and not string: (?P<id>\d+)
I hope those help you, and once again, do read the handbook for a more detailed guide.
The Corrected Code
add_action( 'rest_api_init', 'helloTest' );
function helloTest() {
register_rest_route( 'hello/v1', 'hello/(?P<id>\d+)', array(
'methods' => WP_REST_SERVER::READABLE,
'callback' => 'showHello'
) );
}
function showHello( $request ) {
return new WP_REST_Response( wp_get_current_user()->user_login, 200 );
}
Now about getting the user (from the API endpoint — showHello())
If I have to authenticate again, how to add a "nonce" to it?
Just because the user is logged-in/authenticated to the (WordPress) site, it doesn't mean the user is automatically logged-in to the WP REST API. So yes, you'd need to either provide a nonce along with your API request, or use one of the authentication plugins mentioned right here.
Now in most cases, GET (i.e. read-only) requests to the API do not need any authentication, but if you'd like to retrieve the data of the currently logged-in user on your site, then one way is via the _wpnonce data parameter (either POST data or in the query for GET requests).
Example for a GET request:
http://example.com/wp-json/wp/v2/posts?_wpnonce=<nonce>
So based on your comment and the corrected code (above):
Theres no "code" that make the request. Its is just an anchor that
calls my route: Hello
You can add the nonce as part of the URL query string like so: (the namespace is hello/v1 and the <id> is 1)
// Make request to /wp-json/hello/v1/hello/<id>
$nonce = wp_create_nonce( 'wp_rest' );
echo 'Hello';
So try that out along with the corrected code and let me know how it goes. :)
And once again, be sure to read the REST API authentication handbook.

Resources