Jump to content

LoginPassKey


psy
 Share

Recommended Posts

  • 3 weeks later...
3 hours ago, Ivan Gretsky said:

Seems to be a great module, @psy. Just maybe a video or some screenshots could make it easier to understand what exactly it does without installing?

Thanks Ivan 🙂 

Have just released version 0.0.3 which 🤞is good to go. Available at https://github.com/clipmagic/LoginPassKey/tree/main

This latest version also adds support for AppApi as well as passkey login for admin and LoginRegisterPro

Will definitely add some screenshots/videos. In the meantime...

Logging into admin:

1258590419_Screenshot2025-04-28at9_00_03pm.png.4938074f3ecb70d73e3f0a9293ab8329.png  1236267524_Screenshot2025-04-28at9_00_48pm.png.c38616dac26cce864fc670d7fd9212ed.png

 

Logging in with LoginRegisterPro on the frontend:

 image.png.c58707d0bcf330ee0ff12e452389ce35.png 376167972_Screenshot2025-04-28at9_03_31pm.png.cdc4555189c95e20c986fecfda1e8928.png

 

and when a user passkey login fails:

image.png.028a87635e20eec0cc257e861c4af250.png

  • Like 2
Link to comment
Share on other sites

  • 4 weeks later...

Hi.
I have fresh install of PW 3.0.248 (dev) and installed your module and after installing it showed this error:

Fatal Error: Uncaught Error: Call to undefined function _() in site/modules/LoginPassKey/LoginPassKey.module:48

#0 wire/core/ModulesConfigs.php (588): LoginPassKey->getModuleConfigInputfields()
#1 wire/core/Modules.php (1744): ModulesConfigs->getModuleConfigInputfields()
#2 wire/core/Wire.php (419): Modules->___getModuleConfigInputfields()
#3 wire/core/WireHooks.php (998): Wire->_callMethod()
#4 wire/core/Wire.php (484): WireHooks->runHooks()
#5 wire/modules/Process/ProcessModule/ProcessModule.module (1705): Wire->__call()
#6 wire/modules/Process/ProcessModule/ProcessModule.module (1435): ProcessModule->renderEdit()
#7 wire/core/Wire.php (413): ProcessModule->___executeEdit()
#8 wire/core/WireHooks.php (998): Wire->_callMethod()
#9 wire/core/Wire.php (484): WireHooks->runHooks()
#10 wire/core/ProcessController.php (361): Wire->__call()
#11 wire/core/Wire.php (413): ProcessController->___execute()
#12 wire/core/WireHooks.php (998): Wire->_callMethod()
#13 wire/core/Wire.php (484): WireHooks->runHooks()
#14 wire/core/admin.php (174): Wire->__call()
#15 site/templates/admin.php (18): require('...')
#16 wire/core/TemplateFile.php (328): require('...')
#17 wire/core/Wire.php (413): TemplateFile->___render()
#18 wire/core/WireHooks.php (998): Wire->_callMethod()
#19 wire/core/Wire.php (484): WireHooks->runHooks()
#20 wire/modules/PageRender.module (581): Wire->__call()
#21 wire/core/Wire.php (416): PageRender->___renderPage()
#22 wire/core/WireHooks.php (998): Wire->_callMethod()
#23 wire/core/Wire.php (484): WireHooks->runHooks()
#24 wire/core/WireHooks.php (1099): Wire->__call()
#25 wire/core/Wire.php (484): WireHooks->runHooks()
#26 wire/modules/Process/ProcessPageView.module (193): Wire->__call()
#27 wire/modules/Process/ProcessPageView.module (114): ProcessPageView->renderPage()
#28 wire/core/Wire.php (416): ProcessPageView->___execute()
#29 wire/core/WireHooks.php (998): Wire->_callMethod()
#30 wire/core/Wire.php (484): WireHooks->runHooks()
#31 index.php (55): Wire->__call()
#32 {main}
thrown (line 48 of site/modules/LoginPassKey/LoginPassKey.module)

And when I click on menu in admin - access - passkeys I see this:

SQLSTATE[42S02]: Base table or view not found: 1146 Table 'pw.loginpasskey' doesn't exist

Do you know where could be problem ?
Installation is on machine dedicated with OS FreeBSD 14.2, Apache24, PHP 8.4.5, MySQL 8.4.3
Are there any requirements specific for this module ?
What do you think ?
Pavel

Link to comment
Share on other sites

Hi @Pavel Radvan
Thanks for bringing this to my attention.

30 minutes ago, Pavel Radvan said:
Fatal Error: Uncaught Error: Call to undefined function _() in site/modules/LoginPassKey/LoginPassKey.module:48

This error relates to text strings. The strictness of PHP 8.4.5 may be triggering the issue as it works on PHP versions below this. I've updated the module in GitHub and should now be OK for 8.4.5.

42 minutes ago, Pavel Radvan said:
SQLSTATE[42S02]: Base table or view not found: 1146 Table 'pw.loginpasskey' doesn't exist

It appears the db table failed to create. Again, it may be related to later versions, in this case MYSQL.

Please uninstall and replace the LoginPassKey.module file with the latest GitHub version at https://github.com/clipmagic/LoginPassKey/blob/main/LoginPassKey.module, then re-install.

Let me know the result.

 

 

Link to comment
Share on other sites

28 minutes ago, psy said:

Hi @Pavel Radvan
Thanks for bringing this to my attention.

This error relates to text strings. The strictness of PHP 8.4.5 may be triggering the issue as it works on PHP versions below this. I've updated the module in GitHub and should now be OK for 8.4.5.

It appears the db table failed to create. Again, it may be related to later versions, in this case MYSQL.

Please uninstall and replace the LoginPassKey.module file with the latest GitHub version at https://github.com/clipmagic/LoginPassKey/blob/main/LoginPassKey.module, then re-install.

Let me know the result.

 

 

Hi.
Thanks very much for your reply.
I tried to donwload module and then upload it with changed file from you.
Module is installed without errors, but there are still errors when I enable module and passkey for admin (my only user...):

Deprecated: Passing E_USER_ERROR to trigger_error() is deprecated since 8.4, throw an exception or call exit with a string message instead in /usr/local/www/apache24/dev.webantique.cz/index.php on line 64

Hey now… Error: Exception: SQLSTATE[42S02]: Base table or view not found: 1146 Table 'pw.loginpasskey' doesn't exist (in wire/core/WireDatabasePDOStatement.php line 168)

#0 wire/core/WireDatabasePDOStatement.php (168): PDOStatement->execute()
#1 wire/core/WireDatabasePDOStatement.php (148): WireDatabasePDOStatement->executeDebug()
#2 site/modules/LoginPassKey/LoginPassKey.module (602): WireDatabasePDOStatement->execute()
#3 site/modules/LoginPassKey/LoginPassKey.module (676): LoginPassKey->_getCredentialsFromDB()
#4 site/modules/LoginPassKey/LoginPassKey.module (399): LoginPassKey->preRegisterUser()
#5 wire/core/WireHooks.php (1099): LoginPassKey->registerAdmin()
#6 wire/core/Wire.php (484): WireHooks->runHooks()
#7 wire/modules/Process/ProcessPageView.module (193): Wire->__call()
#8 wire/modules/Process/ProcessPageView.module (114): ProcessPageView->renderPage()
#9 wire/core/Wire.php (416): ProcessPageView->___execute()
#10 wire/core/WireHooks.php (998): Wire->_callMethod()
#11 wire/core/Wire.php (484): WireHooks->runHooks()
#12 index.php (55): Wire->__call()
#13 {main}

This error message was shown because: you are logged in as a Superuser. Error has been logged.

Other error from admin menu is still showing about missing table....
I had to delete module and then remove from db ...that error was blocking me from access to admin...

Link to comment
Share on other sites

Thanks @Pavel Radvan

This needs more investigation. The install should have thrown an error if the table wasn't created. Do you have access to PHPMyAdmin (or TracyDebugger's Adminer) to confirm the database table does not exist?

Link to comment
Share on other sites

After checking of tablets - there is no table "loginpasskey" in my database which is named pw.
So this could be that problem...

After install of module is this error:

c71078fe-7e2a-4ebe-b117-0eb2ddc0de94.png

After enabling passkey for admin:

DOException #42S02
SQLSTATE[42S02]: Base table or view not found: 1146 Table 'pw.loginpasskey' doesn't exist searchâ–º
File: .../dev.webantique.cz/wire/core/WireDatabasePDOStatement.php:168

Let me know what do you think..

Pavel

Link to comment
Share on other sites

54 minutes ago, Pavel Radvan said:
pw.loginpasskey

The table name should be 'loginpasskey', not 'pw.loginpasskey'. This may be the clue

Link to comment
Share on other sites

Not at all. So you could make some repair of it ?
And yes..."pw" is name of db so table should be probably loginpasskey as you noticed 
For me it is quite good module, because in current days lots of systems recommends use of passkeys...
 

Link to comment
Share on other sites

Posted (edited)

I'm looking into it now.

By the way, the error '1170 BLOB/TEXT' is puzzling too. The 'credential_id' column is not indexed. The only key in the table is the user_id with a fixed length.

Here are the two functions that seem to be the culprits:
 

    public function getTableName() : string
    {
        return wire('sanitizer')->pageName($this->className());
		// could probably be changed to:
		return $this->className(['lowercase']);
    }

    protected function _createTable()
    {
        $sql =  "DROP TABLE IF EXISTS `" . $this->getTableName() ."`;" .
            "CREATE TABLE `" . $this->getTableName() . "`(".
            "id INT(10) NOT NULL AUTO_INCREMENT, " .
            "user_id INT(10) UNSIGNED NOT NULL, " .
            "credential_id TEXT NOT NULL UNIQUE, " .
            "public_key TEXT NOT NULL UNIQUE, " .
            "created TIMESTAMP NOT NULL default CURRENT_TIMESTAMP, " .
            "PRIMARY KEY (id), " .
            "INDEX user_id_index (user_id) " .
            ") CHARSET=utf8";

        $db = $this->getDatabase();
        return $db->exec($sql);
    }

One thing to try is to remove 'UNIQUE' from the 'credential_id' and 'public_key' columns. Maybe MYSQL has trouble ensuring BLOB/TEXT fields are unique? Uninstall and reinstall.

Please let me know if you spot any obvious mistake. 🙂 

Will get back to you asap.

The 'UNIQUE' constraint on the 'credential_id' and 'public_key' columns is definitely an issue with later versions of MYSQL. Updated on GitHub.

Edited by psy
updated
  • Like 1
Link to comment
Share on other sites

Question... When using LoginPassKey on the frontend, eg with LoginRegisterPro, if the passkey isn't recognised, the user is prompted to use their password.

I deliberately hid this message for admin logins in keeping with Ryan's choice to not notify what went wrong.

Would it be helpful for passkey admin login attempts to be warned "Failed to verify your passkey. Please use your password to log in."?

After installing and configuring the module, the admin must logout, then re-login using their password as the passkey isn't yet registered.

On logging-in with their password, and if their device supports it, the admin is asked to register their passkey. Subsequent logins with passkey will work.

Link to comment
Share on other sites

12 hours ago, psy said:

I'm looking into it now.

By the way, the error '1170 BLOB/TEXT' is puzzling too. The 'credential_id' column is not indexed. The only key in the table is the user_id with a fixed length.

Here are the two functions that seem to be the culprits:
 

    public function getTableName() : string
    {
        return wire('sanitizer')->pageName($this->className());
		// could probably be changed to:
		return $this->className(['lowercase']);
    }

    protected function _createTable()
    {
        $sql =  "DROP TABLE IF EXISTS `" . $this->getTableName() ."`;" .
            "CREATE TABLE `" . $this->getTableName() . "`(".
            "id INT(10) NOT NULL AUTO_INCREMENT, " .
            "user_id INT(10) UNSIGNED NOT NULL, " .
            "credential_id TEXT NOT NULL UNIQUE, " .
            "public_key TEXT NOT NULL UNIQUE, " .
            "created TIMESTAMP NOT NULL default CURRENT_TIMESTAMP, " .
            "PRIMARY KEY (id), " .
            "INDEX user_id_index (user_id) " .
            ") CHARSET=utf8";

        $db = $this->getDatabase();
        return $db->exec($sql);
    }

One thing to try is to remove 'UNIQUE' from the 'credential_id' and 'public_key' columns. Maybe MYSQL has trouble ensuring BLOB/TEXT fields are unique? Uninstall and reinstall.

Please let me know if you spot any obvious mistake. 🙂 

Will get back to you asap.

The 'UNIQUE' constraint on the 'credential_id' and 'public_key' columns is definitely an issue with later versions of MYSQL. Updated on GitHub.

Hi.
So I could test it again ?

Link to comment
Share on other sites

Hi

On 5/25/2025 at 10:25 PM, Pavel Radvan said:

So I could test it again ?

Yes, please.
If you get the error again, it's because the module didn't install correctly last time and so wasn't uninstalled properly. To fix:

  1. Delete or rename the folder in site/modules to .LoginPassKey and reload the page to get you back into the admin area
  2. Go to Modules and Refresh
  3. You should get a warning LoginPassKey and ProcessLoginPassKey exist in the database but the files could not be found
  4. For each, click the Edit link and check the box to remove the entries from the modules database table
  5. Places to look for leftover bits in the admin area:
    - /pages/LoginPassKey API - delete this page
    - /setup/templates - delete the lpk-api template
    - /admin/access/passkeys - delete this page
    - empty the trash to ensure they're gone for good

You should now have a clean site to reinstall.

PS: you can use this process to clean up any modules that failed to uninstall correctly.
 

  • Like 1
Link to comment
Share on other sites

Latest version is not showing any errors.
I just need to explore settings more..I just enabled in backend and filled in what was required.
Then I saw popout from my password manager to save passkey.
I confirmed ..
But when I wanted to login back I tried to use passkey, but nothing happened.
So I think I will need some more configuration ? When I look in passkeys I do not see anything...
How I could add passkey to my user - it is superuser admin of PW...???

Link to comment
Share on other sites

1 hour ago, Pavel Radvan said:

Latest version is not showing any errors.

That's great! The popup shows you've already passed some tests:

  1. Your device supports WebAuthn
  2. Your user role is permitted to use WebAuthn
  3. There is no matching registration in the database and you're being invited to register

Couple of things to check:

  1. Where there any errors in the log?
  2. I forgot to include, delete the lpk-api template after deleting the page when manually uninstalling (will edit the post). Please check that the template for the lpk-api page is called lpk-api, and not for example lpk-api-1
  3. Are you using SSL? This is requirement for WebAuthn
Link to comment
Share on other sites

Hi @Pavel Radvan

I'm using the module successfully on a number of sites.

Today I launched a new site ported from my dev server.

The PassKey was for admin only. After logging in with email, then deleting the old passkey (Access->PassKeys) and changing the Host Name in the LoginPassKey module config, logging out and logging again, I was invited to register a new passkey. It registered and saved to the db.

I logged out and successfully logged in with the PassKey.

Truly curious to know why it's not working for you.

What devices are you using? In my case it's a MacBook Pro and the PassKey is saved in Apple KeyChain, ie the key is saved on my MacBook and because Apple KeyChain federates, I can log in with my Face ID on my iPhone.

Link to comment
Share on other sites

On 5/27/2025 at 11:58 PM, psy said:

That's great! The popup shows you've already passed some tests:

  1. Your device supports WebAuthn
  2. Your user role is permitted to use WebAuthn
  3. There is no matching registration in the database and you're being invited to register

Couple of things to check:

  1. Where there any errors in the log?
  2. I forgot to include, delete the lpk-api template after deleting the page when manually uninstalling (will edit the post). Please check that the template for the lpk-api page is called lpk-api, and not for example lpk-api-1
  3. Are you using SSL? This is requirement for WebAuthn

Hi.
I am sorry I am now quite busy with some project.
I did not even updated your module ...I will try it on weekend.
Thinks to check - there were no errors, template is named lpk-api. I am using SSL with certificate (wildcard) for my domain.
When I tried login again I was asked for saving passkey from my password app which is Dashlane, when I did not accepted, Windows Hello popup appeared and then when I confirmed auth it created record in passkeys..
But again when I logged off and tried to login again and clicked on Login with passkey - nothing happened..
I will try on weekend more and let you know
 

Link to comment
Share on other sites

Thanks @Pavel Radvan

I think I know what the problem may be. When you get a chance to test, please:

  1. Grab the latest version of the module from GitHub - all the files
  2. Open your browser dev tools to the console tab on the admin login page
  3. Go through the process again
  4. The console tab (and under the login form) should display a message about what happened.

I suspect it's saying "Sorry, your browser does not support this feature" because of the way Windows Hello handles passkeys. If this is the case, in LoginPassKey.js, comment out the following:
 

        // check browser support
        if (!window.fetch || !navigator.credentials || !navigator.credentials.create) {
            $data = {
                fn: 'end',
                next: 'end',
                errno: 1
            }
             return await connectPost(data,url).then(
                 (res) => {
                     if (res.end) return res
                 }
             )
        }

Please try again and let me know.

Appreciate your help 🙂 

Link to comment
Share on other sites

@Pavel Radvan more...

On 5/28/2025 at 7:46 AM, Pavel Radvan said:

So I think I will need some more configuration ?

If that doesn't work, then it points to a Windows Hello config issue. I've made the module as broad as possible, to allow hybrid platform logins. There is no Windows OS for mobile, and while the doco indicates that WebAuthn SHOULD work on Windows Hello, to quote a Reddit article, "Webauthn is not nearly as confusing on other platforms.". 

 

 

 

Link to comment
Share on other sites

Hi @Pavel Radvan

One more thing to check before changing any code...

Is your /lpk-api/ page viewable/accessible to guests on the frontend? It MUST be in order for the process to work.

This page is a very simple API. If you're looking for something more sophisticated, I recommend using the AppAPI module instead. See the LoginPassKeyAppApi.php file in the examples folder for instructions.

Link to comment
Share on other sites

Another thing to check... The WebAuthn spec is very specific.

If in the LoginPassKey module config field "Host name" by default is "mysite.com" and your .htaccess file changes it to "www.mysite.com" (or vice versa), the check will fail. The "Host name" field, aka "Relying Party" MUST match the URL served to the user.

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

×
×
  • Create New...