I want to use the Element API plugin, but the content must only be visible when users are logged in. How I do this for a section? Is it possible to use requirelogin
or currentUser
for this?
2 Answers
If you want to restrict the whole API, you can add some code to the top of your /config/elementapi.php
file (right below namespace Craft;
) that checks for a logged in user, and ends the request with an appropriate status if the user isn't logged in:
<?php
namespace Craft;
$user = craft()->userSession->getUser();
if (!$user) {
HeaderHelper::setHeader(array('status' => 404));
craft()->end();
}
Note that you can replace the 404
with another HTTP status code if you want to; pick whatever feels appropriate to your app.
If you want to restrict specific endpoints, but leave others open, the best approach is probably to wrap the above code in a function, i.e.
<?php
namespace Craft;
function requireLogin() {
$user = craft()->userSession->getUser();
if (!$user) {
HeaderHelper::setHeader(array('status' => 404));
craft()->end();
}
}
return [
...
Then, it's simply a matter of calling this function from your restricted endpoints' transformer
callbacks:
'news.json' => [
'elementType' => 'Entry',
'criteria' => ['section' => 'news'],
'transformer' => function(EntryModel $entry) {
// This endpoint should be restricted
requireLogin();
return [
'title' => $entry->title,
...
];
},
],
...
-
Thanx @Mats tried it today and works like a charm, I also added basic authentication for usage in an app Commented Nov 26, 2016 at 13:29
-
Is it possible to add an array in the craft()->end(); tag? On fail login I want to return a json object wit 'status' => 'error' or something like that Commented Dec 2, 2016 at 10:14
-
1@MaartenHeideman Yes, that's possible – something like this would work fine:
craft()->end(JsonHelper::encode(['status' => 'error']));
Commented Dec 2, 2016 at 10:26 -
You should probably not use HTTP status 404 if you're returning an error object though. Commented Dec 2, 2016 at 10:27
For the people who needs something similar. The basic auth function for the Element API.
function requireLogin()
{
header("Access-Control-Allow-Origin: *");
header("Access-Control-Allow-Headers: X-Requested-With");
if (craft()->userSession->isLoggedIn()) {
// you are authenticated
} else {
// check params
$loginName = craft()->request->getQuery('loginName');
$password = craft()->request->getQuery('password');
if (craft()->userSession->login($loginName, $password)) {
// login success
$user = craft()->userSession->getUser();
} else {
// login fails echo message
$errorCode = craft()->userSession->getLoginErrorCode();
$errorMessage = craft()->userSession->getLoginErrorMessage($errorCode, $loginName);
craft()->end(JsonHelper::encode(array('data' => array( ['status' => 'error','message' =>'wrong login'] ))));
}
}
}
And you use these params in your url: ?loginName=username&password=yourpass
-
FTR, I'd highly recommend not passing username/passwords combinations in the querystring as it opens up all sorts of security related issues. You can use some alternative authentication methods, such as token based.– Brad Bell ♦Commented Oct 16, 2018 at 17:05
-
1