I am trying to use the Magento 2 Rest API, using token authorization. I can successfully POST user/password to /rest/V1/integration/admin/token/, and I get a token returned. But when I try to GET data back from one of the endpoints using the token in an Authorization Bearer heading, I get an HTTP 401 Basic Authentication error. The problem is that the server requires Basic Authentication, but there is no way I know of to get both Basic and Bearer authentication into one request. If I just specify the Basic header on the GET request then I get a Magento message back to tell me I don't have access to the resource, which is fair enough since I haven't given it a token.
My code is:
<?php
// Get handle for token retrieval
$userData = array("username" => "user", "password" => "password!");
$ch = curl_init("https://my.magento/rest/V1/integration/admin/token/");
// Set options
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST");
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($userData));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, array("Content-Type: application/json", "Content-Length: " . strlen(json_encode($userData))));
curl_setopt($ch, CURLOPT_VERBOSE, true);
$verbose = fopen('/tmp/curl.log', 'w+');
curl_setopt($ch, CURLOPT_STDERR, $verbose);
// Get token
$token = curl_exec($ch);
echo "Token returned: " . $token . "<BR><BR>";
// Display log
rewind($verbose);
$verboseLog = stream_get_contents($verbose);
echo "Verbose information 1:\n<pre>", htmlspecialchars($verboseLog), "</pre>\n";
echo "About to get product<BR>";
// Get handle for product types
$ch = curl_init("https://my.magento/rest/V1/products/types/");
// Set options
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "GET");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, array("Content-Type: application/json", "Authorization: Bearer " . json_decode($token)));
curl_setopt($ch, CURLOPT_VERBOSE, true);
$verbose = fopen('/tmp/curl.log', 'w+');
curl_setopt($ch, CURLOPT_STDERR, $verbose);
// Get types
$result = curl_exec($ch);
echo "Result: " . $result . "<BR>";
// Display log
rewind($verbose);
$verboseLog = stream_get_contents($verbose);
echo "<BR>Verbose information 2:\n<pre>", htmlspecialchars($verboseLog), "</pre>\n";
?>
And the browser output is:
Tokenreturned: "t8iskt68xlo5frf9hhtc1lk8wmqzbzx8"
Verbose information 1:
* About to connect() to my.magento port 443 (#2)
* Trying nn.nn.nn.nn...
* Connected to mymagento (nn.nn.nn.nn) port 443 (#2)
* CAfile: /etc/pki/tls/certs/ca-bundle.crt
CApath: none
* SSL connection using TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
* Server certificate:
* subject: CN=ssl379212.cloudflaressl.com,OU=PositiveSSL Multi-Domain,OU=Domain Control Validated
* start date: Oct 26 00:00:00 2018 GMT
* expire date: May 04 23:59:59 2019 GMT
* common name: ssl379212.cloudflaressl.com
* issuer: CN=COMODO ECC Domain Validation Secure Server CA 2,O=COMODO CA Limited,L=Salford,ST=Greater Manchester,C=GB
> POST /rest/V1/integration/admin/token/ HTTP/1.1
Host: sand2.firetoys.co.uk
Accept: */*
Content-Type: application/json
Content-Length: 48
* upload completely sent off: 48 out of 48 bytes
< HTTP/1.1 200 OK
< Date: 2018年10月31日 12:50:01 GMT
< Content-Type: application/json; charset=utf-8
< Content-Length: 34
< Connection: keep-alive
< Set-Cookie: __cfduid=d69af7d1f0a1205231a8867c1f45875621540990201; expires=Thu, 31-Oct-19 12:50:01 GMT; path=/; domain=.my.magento; HttpOnly
< X-Frame-Options: SAMEORIGIN
< X-UA-Compatible: IE=edge
< Pragma: no-cache
< Expires: -1
< Cache-Control: no-store, no-cache, must-revalidate, max-age=0
< Accept-Ranges: bytes
< Set-Cookie: PHPSESSID=9p378rsfito8gfocnrufucssh6; expires=Wed, 31-Oct-2018 13:50:01 GMT; Max-Age=3600; path=/; domain=sand2.firetoys.co.uk; secure; HttpOnly
< Expect-CT: max-age=604800, report-uri="https://report-uri.cloudflare.com/cdn-cgi/beacon/expect-ct"
< Server: cloudflare
< CF-RAY: 47263eb629ea0ce9-LHR
<
* Connection #2 to host my.magento left intact
About to get product
Result:
Verbose information 2:
* About to connect() to my.magento port 443 (#3)
* Trying nn.nn.nn.nn...
* Connected to my.magento (nn.nn.nn.nn) port 443 (#3)
* CAfile: /etc/pki/tls/certs/ca-bundle.crt
CApath: none
* SSL connection using TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
* Server certificate:
* subject: CN=ssl379212.cloudflaressl.com,OU=PositiveSSL Multi-Domain,OU=Domain Control Validated
* start date: Oct 26 00:00:00 2018 GMT
* expire date: May 04 23:59:59 2019 GMT
* common name: ssl379212.cloudflaressl.com
* issuer: CN=COMODO ECC Domain Validation Secure Server CA 2,O=COMODO CA Limited,L=Salford,ST=Greater Manchester,C=GB
> GET /rest/V1/products/types/ HTTP/1.1
Host: sand2.firetoys.co.uk
Accept: */*
Content-Type: application/json
Authorization: Bearer t8iskt68xlo5frf9hhtc1lk8wmqzbzx8
< HTTP/1.1 401 Unauthorized
< Date: 2018年10月31日 12:50:01 GMT
< Content-Length: 0
< Connection: keep-alive
< Set-Cookie: __cfduid=d38c9e4bc3019d9ac55c7f68f5c5ca1161540990201; expires=Thu, 31-Oct-19 12:50:01 GMT; path=/; domain=.my.magento; HttpOnly
< X-Varnish: 7995397
< WWW-Authenticate: Basic
< Expect-CT: max-age=604800, report-uri="https://report-uri.cloudflare.com/cdn-cgi/beacon/expect-ct"
< Server: cloudflare
< CF-RAY: 47263eb70f5b3512-LHR
<
* Connection #3 to host my.magento left intact
Any ideas?
3 Answers 3
Make sure that the admin account you are using has the correct permissions set and is allowed to get data from the endpoint.
-
The user has access to everything. I don't think HTTP is letting me get as far as that - if I put in the basic authentication header in place of the bearer token then I get a Magento message about not having access as I haven't supplied a token. If I use the bearer token authorization then I think HTTP is rejecting me before I get to Magento.Matthew– Matthew2018年11月01日 17:33:59 +00:00Commented Nov 1, 2018 at 17:33
-
I checked the code on 2 magento 2.2.6 instances and it works as expected, so most probably the problem lies with some settings in magento (check token valid time) or server (nginx/apache) configuration. If you have access to the server check logs in
var/logandvar/report/to see if there is something. The complete null of response suggests some exception is raised during script execution.Zefiryn– Zefiryn2018年11月01日 23:06:32 +00:00Commented Nov 1, 2018 at 23:06 -
I have some access to the server, but I can't look into most of the files in /var/log (and there doesn't appear to be a /var/report). Which files should I be looking at? But as I say if I run the request with Basic authentication but without the Bearer token I get a Magento response saying I don't have access, as I would expect. I would have thought that if the problem was that the token when I do send it is invalid in some way, then I would get the same Magento error rather than nothing. Anyway, I should know more when I try with basic authentication switched off soon.Matthew– Matthew2018年11月03日 08:45:58 +00:00Commented Nov 3, 2018 at 8:45
-
I meant
var/logandvar/reportin the magento folder, not system/varfolder. If you see error response while not providing the token but nothing when do then I suspect there is an exception and due to production mode being set on the server you have no information about it.Zefiryn– Zefiryn2018年11月04日 08:04:24 +00:00Commented Nov 4, 2018 at 8:04
OK, I have had a chance to test this with basic authentication switched off, and everything works fine. Basic authentication will be off anyway in the live environment, so in the absence of any method of applying both basic and bearer authentication in one request I will have to live with having to store up my testing for occasional days when basic can be switched off.
Thanks to @Zefiryn for your responses.
Basic authentication has to be disabled for rest api requests because one can't authorize with both basic auth and bearer token in the same request, to disable basic auth for api-requests in webserver config use something like:
nginx:
map $request_uri $auth_uri { ~^/rest/ "off"; default "Restricted"; } server { [..] auth_basic $auth_uri; [..]apache (with mod setenvif enabled):
<VirtualHost *:443> [..] SetEnvIf Request_URI ^/rest/ noauth=1 <Directory /path/to/webroot> AuthType Basic [..] Require valid-user Allow from env=noauth Satisfy any Deny from env!=noauth