First things first: This is quite similar to this, yet different.

I'm trying to get authentication/login for Element-API for Craft 3 to work. Meaning I would like to restrict access to certain endpoints that require the client to be logged in and also (essentially, this is the question) have a way to login via the API (or a different way, but preferably over the API).

This is what I got so far:

use Craft;
use craft\elements\Entry;
use craft\helpers\UrlHelper;

function requireLogin(){
    header("Access-Control-Allow-Origin: *");
    header("Access-Control-Allow-Headers: X-Requested-With");

    if (!Craft::$app->user->isGuest) {
        // you are authenticated
    } else {
        // check params
        $loginName = Craft::$app->request->getQueryParam('loginName');
        $password = Craft::$app->request->getQueryParam('password');

        if (Craft::$app->user->login($loginName, $password)) {
            // login success
            $user = Craft::$app->userSession->getUser();
        } else {
            // login fails echo message
            $errorCode = Craft::$app->userSession->getLoginErrorCode();
            $errorMessage = Craft::$app->userSession->getLoginErrorMessage($errorCode, $loginName);
            Craft::$app->end(JsonHelper::encode(array('data' => array( ['status' => 'error','message' =>'wrong login']  ))));


return [

using requireLogin(); inside the transformer of the given endpoint.

Most of this is copied from the before mentioned, related link. But as I'm no PHP developer I kind of struggle getting it to work. The error I get is the following with this code:

Argument 1 passed to yii\web\User::login() must be an instance of yii\web\IdentityInterface, null given as a result of Craft::$app->user->login($loginName, $password)

I do understand whats happening and am capable of reading the error, but I'm not very familiar with yii, nor PHP. If someone could point out what needs to be done, which problems also might occur of if I'm on the wrong track or even post a working solution, I would be very grateful.

1 Answer 1


First of all passing the password and username as query strings is one of the most insecure things you can do. It would highly suggest you to not do that unless you want to expose your accounts to everyone with minor knowledge.

Furthermore you are mixing Craft 2 with Craft 3. There is no userSession in Craft 3. I don't want to post a code snipped that would work with the way you are trying since would could eventually copy it without knowing the harm it might cause.

In the end: you should either create some kind of access token, don't pass the params via get request or do something similar. Globally passing sensitive data via url is not clever

  • Thanks for the answer. So essentially I would create a access tokens beforehand and hand them out to the users (or provide them in the frontend) that should be allowed to access the API and then check within the API if it was requested via one of the tokens? Commented Oct 13, 2018 at 18:01
  • Yes. That's correct. Otherwise everyone can see the login name and password of your users. When you do it via token, they can only see the token and are "just" able to take advantage of the api but not of the entire account. The easiest and most secure way is still to just let them login normally via Craft and check if a current user exists instead of making some kind of pseudo oAuth Commented Oct 14, 2018 at 8:37
  • I understand. Unfortunately I try to use the Element-API as API for an app. So the actual device wont login itself and thus Craft::$app->user->isGuest will always fail as the device doing the request will always be a guest. So I'm required to have some sort of token generated by myself. Probably going to wait for the OAuth plugin if it comes available. Or is there any other build in, secure way inside Craft to easily archive this? Commented Oct 16, 2018 at 11:33
  • 1
    Your solution would be a login as well? I don't see the disadvantage of a normal login? The user needs to insert the login name and password anyway Commented Oct 16, 2018 at 13:12
  • I actually want to get rid of the login completely (for now). I know this sounds strange but the goal is to have multiple mobile apps, each used by many people. Each mobile app should get the data from the API (so no user login for now as the data is not related to the end-user/person). I would like to include the "access-token" of a "craft-user" inside each app. So essentially the app is the "craft user". The apps can't login as there wont be any UI for that, neither should a normal person be able to register as a craft-user. I'm sorry, if this is confusing. It's just for data inside the apps Commented Oct 16, 2018 at 16:03

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.