Focuses on API authentication, access scopes, and permission management.
Hello,
Firstly, to provide context to my project, I aim to develop a PHP application with Symfony that allows me to manage my store and customers in a "Headless".
Like to Hydrogen, I want my customers to be able to login using the 6-digit code login offered by Shopify.
I am using the Customer API to obtain an accessToken, so I installed the Headless application and configured it as "Confidential."
I also set up my callback URL in the Headless application.
To obtain the login form (with the 6-digit code), I use the URL: https://shopify.com/63XXXXXXX68/auth/oauth/authorize with the parameters described in the documentation.
Here is my code:
$url = sprintf(
'https://shopify.com/%s/auth/oauth/authorize?scope=%s&client_id=%s&redirect_uri=%s&response_type=code&state=%s&nonce=%s&ui_locales=%s',
'63XXXXXXX68',
urlencode('openid email https://api.customers.com/auth/customer.graphql'),
'shp_6958562d-XXXX-XXXX-XXXX-14c6cadacbf2',
urlencode('https://xxxxxxxxx.ngrok.dev/auth/oauth/callback'),
$this->generateState(),
$this->generateNonce(),
'fr'
);
I retrieve the "code" in my callback function, allowing me to execute the following request to obtain the accessToken.
I make a POST request to the following URL: https://shopify.com/63XXXXXXX68/auth/oauth/token, and in the body, I provide the parameters:
Here is my code:
$clientId = 'shp_6958562d-XXXX-XXXX-XXXX-14c6cadacbf2';
$clientSecret = 'a5604f7b8ae661db38cxxxxxxxxxxxxxxxxxxxxxxxxxxxx95e699362cbdb9597';
$code = $request->query->all()['code'];
$credentials = hash('sha256', $clientId . ':' . $clientSecret);
$response = $this->client->request(
'POST',
sprintf('https://shopify.com/%s/auth/oauth/token', '63XXXXXXX68'),
[
'headers' => [
'content-type: application/x-www-form-urlencoded',
'Authorization' => 'Basic ' . $credentials,
],
'body' => [
'grant_type' => 'authorization_code',
'client_id' => $clientId,
'code' => $code,
'redirect_uri' => urlencode('https://xxxxxxxxx.ngrok.dev/auth/oauth/callback'),
],
],
);
In the header, I add the "Authorization" parameter with the value being the hash256 of the concatenation of the clientId and clientSecret keys provided by the Headless application.
Unfortunately, I encounter a 400 error with the following JSON response:
{"error":"invalid_request","error_description":"Multiple client credentials are provided."}
Thank you.
Solved! Go to the solution
This is an accepted solution.
After conducting research, I found a solution.
In the documentation (https://shopify.dev/docs/api/customer#step-obtain-access-token), the "Authorization" header seems to be unnecessary.
Instead, in the body of the "accessToken" request, I need to include the "client_secret" like this:
$response = $this->client->request(
'POST',
sprintf('https://shopify.com/%s/auth/oauth/token', $shopify['shop_id']),
[
'headers' => [
'Content-Type' => 'application/x-www-form-urlencoded',
],
'body' => [
'grant_type' => 'authorization_code',
'client_id' => $clientId,
'client_secret' => $clientSecret,
'code' => $code,
'redirect_uri' => 'https://lighthouse.ngrok.dev/auth/oauth/callback',
],
],
);
And I removed the urlencode in the redirect_uri in the 2 requests.
This is an accepted solution.
After conducting research, I found a solution.
In the documentation (https://shopify.dev/docs/api/customer#step-obtain-access-token), the "Authorization" header seems to be unnecessary.
Instead, in the body of the "accessToken" request, I need to include the "client_secret" like this:
$response = $this->client->request(
'POST',
sprintf('https://shopify.com/%s/auth/oauth/token', $shopify['shop_id']),
[
'headers' => [
'Content-Type' => 'application/x-www-form-urlencoded',
],
'body' => [
'grant_type' => 'authorization_code',
'client_id' => $clientId,
'client_secret' => $clientSecret,
'code' => $code,
'redirect_uri' => 'https://lighthouse.ngrok.dev/auth/oauth/callback',
],
],
);
And I removed the urlencode in the redirect_uri in the 2 requests.