The documentation at http://devdocs.magento.com/guides/v2.2/get-started/authentication/gs-authentication-session.html states:
"For example, if a customer is logged in to the Magento storefront and the JavaScript widget invokes the self API, details for the logged-in customer are fetched:
GET /rest/V1/customers/me
_Similarly, if an admin is logged in to the Magento Admin and the JavaScript widget Magento_Customer::group API, details for the logged-in admin are fetched. The web API framework establishes the identity of the admin user based on logged-in session information and authorizes access to the Magento_Customer::group resource._"
<script>
require([
'jquery'
], function ($) {
// Does not work
$.ajax({
method: 'GET',
url: '/rest/V1/orders',
contentType: 'application/json'
});
// Works
$.ajax({
method: 'POST',
url: '/rest/default/V1/integration/admin/token',
data: JSON.stringify({
username: 'admin',
password: 'password123'
}),
dataType: 'JSON',
contentType: 'application/json'
}).done(function(response) {
$.ajax({
method: 'GET',
url: '/rest/V1/orders',
data: {"searchCriteria":{"filter_groups":[{"filters":[]}],"current_page":1,"page_size":100}},
dataType: 'JSON',
contentType: 'application/json',
beforeSend: function (xhr) {
xhr.setRequestHeader('Authorization', 'Bearer ' + response);
}
});
});
});
</script>
The response (with sample data) should return the following (cut short for readability):
{"items":[{"applied_rule_ids":"1","base_currency_code":"EUR","base_discount_amount":0,"base_discount_invoiced":0,"base_grand_total":36.39,"base_discount_tax_compensation_amount":0,"base_discount_tax_compensation_invoiced":0,"base_shipping_amount":5,"base_shipping_discount_amount":0,"base_shipping_incl_tax":5,"base_shipping_invoiced":5,"base_shipping_tax_amount":0,"base_subtotal":29,"base_subtotal_incl_tax":31.39,"base_subtotal_invoiced":29,"base_tax_amount":2.39,"base_tax_invoiced":2.39,"base_total_due":0,"base_total_invoiced":36.39,"base_total_invoiced_cost":0,"base_total_paid":36.39,"base_to_global_rate":1,"base_to_order_rate":1,"billing_address_id":2,"created_at":"2018-03-22 20:56:43","customer_dob":"1973-12-15 00:00:00","customer_email":"[email protected]"
...
The response to query using session based authentication returns the following:
{"message":"Consumer is not authorized to access %resources","parameters":{"resources":"Magento_Sales::sales"}}
It seems like it has to do with duplicate sessions/cookies; the "PHPSESSID" cookie is used for the REST API but the "admin" cookie is used for admin. So session based authentication fails because the REST request reads from another session/cookie.
The following cURL can be used to reproduce the issue. With "my-session-id" set to the "admin" cookie session value, it works, with the "PHPSESSID" cookie session value it fails.
curl 'http://my-domain.com/rest/default/V1/orders' \
-H 'Cookie: PHPSESSID=my-session-id;' \
-H 'Content-Type: application/json' \
-H 'X-Requested-With: XMLHttpRequest'
The Github issues are only for issues within Magento 2. You're trying to use the REST API for a JavaScript, which is incorrect. The REST API for products seems to work just fine in Magento, if you set the permissions right.
For questions like this, please ask your question on the Magento Community Forums or StackOverflow.
@ArjenMiedema What do you mean with "You're trying to use the REST API for a JavaScript, which is incorrect."?
The documentation at http://devdocs.magento.com/guides/v2.2/get-started/authentication/gs-authentication-session.html states:
"For example, if a customer is logged in to the Magento storefront and the JavaScript widget invokes the self API, details for the logged-in customer are fetched:
GET /rest/V1/customers/me
Similarly, if an admin is logged in to the Magento Admin and the JavaScript widget Magento_Customer::group API, details for the logged-in admin are fetched. The web API framework establishes the identity of the admin user based on logged-in session information and authorizes access to the Magento_Customer::group resource."
Which would mean that this, in an adminhtml template, should work...
<script>
require([
'jquery'
], function ($) {
// Does not work
$.ajax({
method: 'GET',
url: '/rest/V1/customers/me',
contentType: 'application/json'
});
// Works
$.ajax({
method: 'POST',
url: '/rest/default/V1/integration/admin/token',
data: JSON.stringify({
username: 'admin',
password: 'password123'
}),
dataType: 'JSON',
contentType: 'application/json'
}).done(function(response) {
$.ajax({
method: 'GET',
url: '/rest/V1/orders',
data: {"searchCriteria":{"filter_groups":[{"filters":[]}],"current_page":1,"page_size":100}},
dataType: 'JSON',
contentType: 'application/json',
beforeSend: function (xhr) {
xhr.setRequestHeader('Authorization', 'Bearer ' + response);
}
});
});
});
</script>
I've read the source, but cannot find any reference to the session in the REST handler which leads me to believe that there is a bug with session based authentication.
Seems like it's a bug:
https://github.com/magento/magento2/issues/9138
I debugged with xdebug, and found that the user context is null and chosen user context gets set to guest instead of admin. In AdminSessionUserContext $this->_adminSession->hasUser() returns null on a request although logged in.
.../module-authorization/Model/CompositeUserContext.php
protected function getUserContext()
{
if ($this->chosenUserContext === null) {
/** @var UserContextInterface $userContext */
foreach ($this->userContexts as $userContext) {
if ($userContext->getUserType() && $userContext->getUserId() !== null) {
$this->chosenUserContext = $userContext;
break;
}
}
if ($this->chosenUserContext === null) {
$this->chosenUserContext = false;
}
}
return $this->chosenUserContext;
}
.../module-user/Model/Authorization/AdminSessionUserContext.php
public function getUserId()
{
return $this->_adminSession->hasUser() ? (int)$this->_adminSession->getUser()->getId() : null;
}
Debugging further it seems like it has to do with duplicate cookies; the "PHPSESSID" cookie is used for the REST API but the "admin" cookie is used for admin. So authentication fails because the REST request reads from another session.
Will leave further comments on the other ticket.
@rasmuswikman I was missing the authentication in your initial message. But looking at your reply, you do seem to have authentication in your call. We'll look into it to see if this can be reproduced.
Updated issue description and title to conform to Magento team standards.
So at this moment, there is no way to develop any kind of AJAX module for the backend? Except when you hardcode the admin credentials? Or use some kind of form where admins have to put in their credentials over and over again?
Hello @rasmuswikman, thank you for your report.
We've acknowledged the issue and added to our backlog.
Is there a workaround in the meantime?
Facing the same issue. Not getting custom session in rest api calls. Session based authentication works only with customer or let's say global session. If we modify the path/namespace of session, we don't get the session.
Agree with all the comments by @rasmuswikman.
Hello, we've had to deal with this ourselves. This is actually fairly easy to solve.
Here is an example of how the token is generated.
Send up that token with the Authorization header (example).
Most helpful comment
So at this moment, there is no way to develop any kind of AJAX module for the backend? Except when you hardcode the admin credentials? Or use some kind of form where admins have to put in their credentials over and over again?