Argument 1 must be an instance of Drupal\tcdev\Controller\UserAuth, instance of Drupal\user\UserAuth given I want to programmatically log in a user with a custom controller. I want to pass my data with $_POST to the route (I pass data from a mobile application); if username and password are correct, the method/function should return TRUE.

The route is the following one.

tcdev.login:
  path: '/tclogin'
  defaults:
    _controller: 'Drupal\tcdev\Controller\MYCenterController::login'
    _title: 'Login call back'
  requirements:
    _permission: 'access content'


The code for the controller is the following one.    

namespace  Drupal\tcdev\Controller;

use Drupal\Core\Controller\ControllerBase;
use Symfony\Component\DependencyInjection\ContainerInterface;

class MyController extends ControllerBase {

    /**
     * \Drupal\user\UserAuth definition.
     *
     * @var \Drupal\user\UserAuth
     */
    protected $userAuth;

    /**
     * {@inheritdoc}
     */
    public function __construct(UserAuth $user_auth) {
        $this-&gt;userAuth = $user_auth;
    }

    /**
     * {@inheritdoc}
     */
    public static function create(ContainerInterface $container) {
        return new static($container-&gt;get('user.auth'));
    }
    }

    public function login() {
        $uid = $this-&gt;userAuth-&gt;authenticate($_POST['user'], $_POST['pass']);
        $acc = User::load($uid);

        //return new Response('Hi ' . $uid);
    }

}


It returns me the following error:


  TypeError: Argument 1 passed to Drupal\tcdev\Controller\MyController::__construct() must be an instance of Drupal\tcdev\Controller\UserAuth, instance of Drupal\user\UserAuth given, called in /Users/yms/Sites/devdesktop/gttc/modules/tcdev/src/Controller/MyController.php on line 32 in Drupal\tcdev\Controller\MyController::__construct() (line 23 of modules/tcdev/src/Controller/MyController.php)


Where is my mistake?
Inject the user.auth in your controller:

$auth = $container-&gt;get('user.auth')


[edited to clarify injection basics:

In public static function create(ContainerInterface $container) add $container->get('user.auth') to the return new static(...) statement.

In public function __construct(...) add the $auth to the signature at the correct position. Then add a private (or protected) variable $auth to your controller and assign the value from __construct to it.

You may simplify that by using drupal console or drush. They can create the boiler plate code for you.

If you don't want to use injection, you may use $auth = \Drupal::service('user.auth');

But this has drawbacks in testability.

[end edit]

then call the authenticate func:

$uid = $auth-&gt;authenticate($username, $pass);


With the $uid load the user:

$acc = User::load($uid);


Then set the user into the session:

  \Drupal::currentUser()-&gt;setAccount($acc);
  \Drupal::logger('user')-&gt;notice('Session opened for %name.', array('%name' =&gt; $acc-&gt;getUsername()));


Should work. But I don't think that it is a good idea to pass around the password in the URL of your tcdev.login...

Edit: Sample Code (generated by drupal generate:controller)

namespace Drupal\preosuser\Controller;

use Drupal\Core\Controller\ControllerBase;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Drupal\user\UserAuth;

/**
 * Class AuthController.
 *
 * @package Drupal\preosuser\Controller
 */
class AuthController extends ControllerBase {

  /**
   * Drupal\user\UserAuth definition.
   *
   * @var \Drupal\user\UserAuth
   */
  protected $userAuth;

  /**
   * {@inheritdoc}
   */
  public function __construct(UserAuth $user_auth) {
    $this-&gt;userAuth = $user_auth;
  }

  /**
   * {@inheritdoc}
   */
  public static function create(ContainerInterface $container) {
    return new static(
      $container-&gt;get('user.auth')
    );
  }

  /**
   * Checklogin.
   *
   * @return string
   *   Return Hello string.
   */
  public function CheckLogin($name) {
    return [
      '#type' =&gt; 'markup',
      '#markup' =&gt; $this-&gt;t('Implement method: CheckLogin with parameter(s): $name'),
    ];
  }

}