3

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 2

5

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,
            ...
        ];

    },
],
...
4
  • 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
0

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

2
  • 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
    I am switched over to the JWT manager Commented Oct 16, 2018 at 17:29

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.