Web login via NFC tag

Hi,
I would like to implement login only via USB nfc reader that enters key ID which allows user to login.
I have sql table with user name and key ID. Login would just compare entered id with database and if match is found then log the user.
I thought of using extra LoginFileds, but it doesnt work with modx 3. Any idea how to implement this?
Thanks

1 Like

Check this out - you should be able to use similar logic for your case.

Ok, but any short hint in code would be appreciated since I am not very strong in coding. How do I compare login id with user in database and then select logged user?

Did you create new users in MODX for your users that should be able to log in? (Entries in the database tables modx_users and modx_user_attributes.)

Where do you store the “key ID”?

user extended field with name KEY

So in the plugin you get a variable $user which is already the correct MODX user.

Then with

$profile = $user->getOne('Profile');

you can access the user profile and with

$extended = $profile->get('extended');

the extended field.

$extended['KEY']

should then give you the “key ID” that you can compare with the variable $password.

Ok I got php code that obtains user username or id. How can I log this user to web context?

For frontend login usually the extra Login is used.

I mean using php code.

Here is a simple code I use on a rest endpoint to login from a Vue page:

public function post() {
    $properties = $this->getProperties();

    $properties = array(
      'login_context' => 'web',
      'username'      => $properties['username'],
      'password'      => $properties['password'],
      'returnUrl'     => "/",
      'rememberme'    => 0,
    );

    $rawResponse = $this->modx->runProcessor('security/login', $properties);
    $response = $rawResponse->getResponse();
    if (!$rawResponse->response["success"]) {
      return $this->failed('Failed login', $response->getResponse(), 401);
    } 


    return $this->success('Login executed',$response->getResponse());
  }

Create a new plugin that runs on the event OnWebAuthentication, like decribed in the article that is linked in the first answer.

I read the article several times but still dont know how to pass specified user to login. So far I only have snippet that return user object.

You don’t have to do that.

You use the Login extra. The Login extra executes the security/login processor. The processor invokes the event OnWebAuthentication and gives you the user object as a parameter.

But I dont use username or password to login, but custom field in user profile ( Bobs ClassExtender ). So if I pass custom key parameter to Login extra is it also passed to plugin with event OnwebAuthentication?

The security/login processor takes the username from the login form and searches for a matching user in the database. If there is such a user, it calls OnwebAuthentication with this user and the value of the password from the login form (parameter $password).


If you don’t use the username from the modUser table as well, then you probably have to extend the class \MODX\Revolution\Processors\Security\Login (particularly the function getUser()) like it is done in the Login extra (to allow login via email-address):

Ok modify Login snippet to use different field instead of email seems like way to go. How do I create this extension without modify login snippet?

I found this article about magic links, which is similar to what I am trying to acomplish.
Logging users in to MODX with magic links | Nathanael McMillan
But there is problem in the code, maybe not working in modx 3?

in modx log:

[2023-03-17 13:30:11] (ERROR @ C:\xampp\htdocs\core\vendor\xpdo\xpdo\src\xPDO\xPDO.php : 666) Could not load class: MagicToken from mysql.magictoken

I always got stuck on
$modx->getObject(‘MagicToken’ or
$modx->newObject(‘MagicToken’
It always return null

Did you create this class “MagicToken”? Did you create it in MODX 3?
In MODX 3, all classes need a namespace. So you have to change the schema from the article you linked.

I changed the schema like this:

<?xml version="1.0" encoding="UTF-8"?>

<model package="Magiclink\Model\" baseClass="xPDO\Om\xPDOObject" platform="mysql" defaultEngine="InnoDB" phpdoc-package="" phpdoc-subpackage="" version="3.0">

      <object class="MagicToken" table="magiclink_tokens" extends="xPDOSimpleObject">
        <field key="token" dbtype="varchar" phptype="string" precision="50" null="false" default="" />
        <field key="userid" dbtype="int" phptype="int" precision="20" null="false" default="" />        
    	<field key="expires" dbtype="datetime" phptype="datetime" null="true" />
    </object>

</model>

I also noticed that path to model is magiclink/src/Model , but in php code it is only magiclink/model