twofactor_u2f icon indicating copy to clipboard operation
twofactor_u2f copied to clipboard

Unable to add YubiKey U2F

Open ahuemmer opened this issue 3 years ago • 16 comments

Steps to reproduce

  1. Try to register YubiKey using Two-Factor U2F

Expected behaviour

U2F registration should succeed

Actual behaviour

No progress is shown in the browser. JavaScript and backend errors are displayed in the development tools (see below).

Server configuration

Operating system: Gentoo Linux

Web server: Nginx 1.18.0-r1

Database: MariaDB 10.4.13-r2

PHP version: 7.4.8-r1

Version: 19.0.1.1 (problem also occurred in the newest 18.x version)

Updated from an older version or fresh install: Updated (several step-by-step-updates beginning with version 14 or 15)

List of activated apps:

Enabled:
  - accessibility: 1.5.0
  - activity: 2.12.0
  - bookmarks: 3.3.3
  - bruteforcesettings: 1.6.0
  - calendar: 2.0.3
  - cloud_federation_api: 1.2.0
  - comments: 1.9.0
  - contacts: 3.3.0
  - contactsinteraction: 1.0.0
  - dav: 1.15.0
  - federatedfilesharing: 1.9.0
  - federation: 1.9.0
  - files: 1.14.0
  - files_pdfviewer: 1.8.0
  - files_rightclick: 0.16.0
  - files_sharing: 1.11.0
  - files_texteditor: 2.11.0
  - files_trashbin: 1.9.0
  - files_versions: 1.12.0
  - files_videoplayer: 1.8.0
  - firstrunwizard: 2.8.0
  - logreader: 2.4.0
  - lookup_server_connector: 1.7.0
  - nextcloud_announcements: 1.8.0
  - notifications: 2.7.0
  - oauth2: 1.7.0
  - password_policy: 1.9.1
  - photos: 1.1.0
  - privacy: 1.3.0
  - provisioning_api: 1.9.0
  - recommendations: 0.7.0
  - serverinfo: 1.9.0
  - settings: 1.1.0
  - sharebymail: 1.9.0
  - support: 1.2.1
  - survey_client: 1.7.0
  - systemtags: 1.9.0
  - tasks: 0.13.3
  - text: 3.0.1
  - theming: 1.10.0
  - twofactor_backupcodes: 1.8.0
  - twofactor_totp: 4.1.3
  - twofactor_u2f: 5.1.0
  - updatenotification: 1.9.0
  - viewer: 1.3.0
  - workflowengine: 2.1.0
Disabled:
  - admin_audit
  - encryption
  - files_external
  - user_ldap

The content of config/config.php:

{
    "system": {
        "instanceid": "***REMOVED SENSITIVE VALUE***",
        "passwordsalt": "***REMOVED SENSITIVE VALUE***",
        "secret": "***REMOVED SENSITIVE VALUE***",
        "trusted_domains": [
            "some.domain",
            "some.other.domain",
            "and.so.on"
        ],
        "datadirectory": "***REMOVED SENSITIVE VALUE***",
        "dbtype": "mysql",
        "version": "19.0.1.1",
        "overwrite.cli.url": "https:\/\/some.domain",
        "overwriteprotocol": "https",
        "dbname": "***REMOVED SENSITIVE VALUE***",
        "dbhost": "***REMOVED SENSITIVE VALUE***",
        "dbport": "3306",
        "dbtableprefix": "oc_",
        "mysql.utf8mb4": true,
        "dbuser": "***REMOVED SENSITIVE VALUE***",
        "dbpassword": "***REMOVED SENSITIVE VALUE***",
        "installed": true,
        "updater.release.channel": "stable",
        "maintenance": false,
        "log_type": "file",
        "logfile": "\/var\/log\/nextcloud\/nextcloud.log",
        "log_authfailip": true,
        "forcessl": true,
        "theme": "",
        "loglevel": 2,
        "memcache.local": "\\OC\\Memcache\\APCu",
        "mail_smtpmode": "sendmail",
        "mail_sendmailmode": "smtp",
        "mail_from_address": "***REMOVED SENSITIVE VALUE***",
        "mail_domain": "***REMOVED SENSITIVE VALUE***",
        "twofactor_enforced": true,
        "twofactor_enforced_groups": [],
        "twofactor_enforced_excluded_groups": [],
        "updater.secret": "***REMOVED SENSITIVE VALUE***"
    }
}

Client configuration

Browser: Firefox 79

Operating system: Windows 10

Logs

Web server error log

(No meaningful entries considering the problem.)

Server log (data/nextcloud.log)
{
   "reqId":"NT9Cp09520MB7moGTqmI",
   "level":3,
   "time":"2020-08-14T14:57:32+00:00",
   "remoteAddr":"123.123.123.123",
   "user":"my_user",
   "app":"index",
   "method":"POST",
   "url":"/apps/twofactor_u2f/settings/finishregister",
   "message":{
      "Exception":"Exception",
      "Message":"Argument 1 passed to OCA\\TwoFactorU2F\\Controller\\SettingsController::finishRegister() must be of the type string, null given, called in /var/www/localhost/htdocs/cloud/lib/private/AppFramework/Http/Dispatcher.php on line 170",
      "Code":0,
      "Trace":[
         {
            "file":"/var/www/localhost/htdocs/cloud/lib/private/AppFramework/App.php",
            "line":137,
            "function":"dispatch",
            "class":"OC\\AppFramework\\Http\\Dispatcher",
            "type":"->"
         },
         {
            "file":"/var/www/localhost/htdocs/cloud/lib/private/AppFramework/Routing/RouteActionHandler.php",
            "line":47,
            "function":"main",
            "class":"OC\\AppFramework\\App",
            "type":"::"
         },
         {
            "function":"__invoke",
            "class":"OC\\AppFramework\\Routing\\RouteActionHandler",
            "type":"->"
         },
         {
            "file":"/var/www/localhost/htdocs/cloud/lib/private/Route/Router.php",
            "line":297,
            "function":"call_user_func"
         },
         {
            "file":"/var/www/localhost/htdocs/cloud/lib/base.php",
            "line":1007,
            "function":"match",
            "class":"OC\\Route\\Router",
            "type":"->"
         },
         {
            "file":"/var/www/localhost/htdocs/cloud/index.php",
            "line":37,
            "function":"handleRequest",
            "class":"OC",
            "type":"::"
         }
      ],
      "File":"/var/www/localhost/htdocs/cloud/lib/private/AppFramework/Http/Dispatcher.php",
      "Line":110,
      "Previous":{
         "Exception":"TypeError",
         "Message":"Argument 1 passed to OCA\\TwoFactorU2F\\Controller\\SettingsController::finishRegister() must be of the type string, null given, called in /var/www/localhost/htdocs/cloud/lib/private/AppFramework/Http/Dispatcher.php on line 170",
         "Code":0,
         "Trace":[
            {
               "file":"/var/www/localhost/htdocs/cloud/lib/private/AppFramework/Http/Dispatcher.php",
               "line":170,
               "function":"finishRegister",
               "class":"OCA\\TwoFactorU2F\\Controller\\SettingsController",
               "type":"->"
            },
            {
               "file":"/var/www/localhost/htdocs/cloud/lib/private/AppFramework/Http/Dispatcher.php",
               "line":100,
               "function":"executeController",
               "class":"OC\\AppFramework\\Http\\Dispatcher",
               "type":"->"
            },
            {
               "file":"/var/www/localhost/htdocs/cloud/lib/private/AppFramework/App.php",
               "line":137,
               "function":"dispatch",
               "class":"OC\\AppFramework\\Http\\Dispatcher",
               "type":"->"
            },
            {
               "file":"/var/www/localhost/htdocs/cloud/lib/private/AppFramework/Routing/RouteActionHandler.php",
               "line":47,
               "function":"main",
               "class":"OC\\AppFramework\\App",
               "type":"::"
            },
            {
               "function":"__invoke",
               "class":"OC\\AppFramework\\Routing\\RouteActionHandler",
               "type":"->"
            },
            {
               "file":"/var/www/localhost/htdocs/cloud/lib/private/Route/Router.php",
               "line":297,
               "function":"call_user_func"
            },
            {
               "file":"/var/www/localhost/htdocs/cloud/lib/base.php",
               "line":1007,
               "function":"match",
               "class":"OC\\Route\\Router",
               "type":"->"
            },
            {
               "file":"/var/www/localhost/htdocs/cloud/index.php",
               "line":37,
               "function":"handleRequest",
               "class":"OC",
               "type":"::"
            }
         ],
         "File":"/var/www/localhost/htdocs/cloud/apps/twofactor_u2f/lib/Controller/SettingsController.php",
         "Line":66
      },
      "CustomMessage":"--"
   },
   "userAgent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:79.0) Gecko/20100101 Firefox/79.0",
   "version":"19.0.1.1"
}
Browser log

From the JavaScript console log:

Just after clicking on "Add U2F device", without any other actions:

Uncaught (in promise) Error: U2F device registration failed (error code unknown)
    rejectRegistration AddDeviceDialog.vue:157
    register AddDeviceDialog.vue:135
    promise callback*register AddDeviceDialog.vue:135
    promise callback*start AddDeviceDialog.vue:105
    VueJS 29
    <anonymous> main-settings.js:52
    Webpack 3
AddDeviceDialog.vue:157
    rejectRegistration AddDeviceDialog.vue:157
    rejectRegistration self-hosted:935
    register AddDeviceDialog.vue:135
    (Async: promise callback)
    register AddDeviceDialog.vue:135
    register self-hosted:935
    (Async: promise callback)
    start AddDeviceDialog.vue:105
    start self-hosted:935
    VueJS 29
    <anonym> main-settings.js:52
    Webpack 3

After naming the device and clicking "Add":

twofactor_u2f: Error persisting registration 
Object { app: "twofactor_u2f", uid: "andy", config: {…}, request: XMLHttpRequest, response: {…}, isAxiosError: true, toJSON: toJSON()
 }
ConsoleLogger.js:54:18
    value ConsoleLogger.js:54
    value ConsoleLogger.js:80
    saveRegistrationData AddDeviceDialog.vue:188
    (Async: promise callback)
    saveRegistrationData AddDeviceDialog.vue:187
    submit AddDeviceDialog.vue:170
    VueJS 26
    start AddDeviceDialog.vue:106
    (Async: promise callback)
    start AddDeviceDialog.vue:106

and

[ERROR] twofactor_u2f: Error: Server error while trying to complete U2F device registration 
Object { app: "twofactor_u2f", uid: "andy" }
ConsoleLogger.js:54:18
    value ConsoleLogger.js:54
    value ConsoleLogger.js:80
    submit AddDeviceDialog.vue:175
    VueJS 26
    start AddDeviceDialog.vue:106
    (Async: promise callback)
    start AddDeviceDialog.vue:106
    VueJS 29
    <anonym> main-settings.js:52
    Webpack 3

The relevant requests I can see in the network tab:

startregister, response (request body was empty), code 200:

{"req":{"version":"U2F_V2","challenge":"ivnkLjiQAZKT5xDXDpRxgplT9jfd7HPxUP9Oz6y2HU4","appId":"https://some.domain"},"sigs":[]}

finishregister, request:

{"name":"Test"}

(No more content!) Response code was 500 with nextcloud standard 500 error page.

Personal remarks

I see a big similarity to #622 and #690 here, but IMHO I have done everything right, following the instructions there (esp. the overwriteprotocol and overwrite.cli.url settings.

The Nextcloud installation is served "directly" by the nginx, no proxy or anything in between.

In the Nextcloud admin tab, there are no open issues ("All checks passed.").

What I tried so far:

  • Uninstall and re-install the app multiple times.
  • ...with or without emptying the oc_twofactor... tables in the db.
  • ...with or without having the TOTP app installed as well.

No luck for now.

Any help would be greatly appreciated! :) Thanks in advance!

ahuemmer avatar Aug 14 '20 15:08 ahuemmer

Seeing the same problem on our installation running Nextcloud 19.0.5.

cogliostro avatar Nov 23 '20 09:11 cogliostro

Uncaught (in promise) Error: U2F device registration failed (error code unknown)

This is the important bit of information. @cogliostro do you see the same in the browser console?

ChristophWurst avatar Nov 23 '20 09:11 ChristophWurst

Yes. But it seems to work in Firefox. It fails in MS Edge ( the new one ).

cogliostro avatar Nov 23 '20 10:11 cogliostro

Also seems to work in Chrome.

cogliostro avatar Nov 23 '20 10:11 cogliostro

Okay but @ahuemmer reported this as not working on Firefox. It could be two unrelated issues.

Also pay close attention to the logged error. Does it contain an error code?

ChristophWurst avatar Nov 23 '20 10:11 ChristophWurst

"Exception":"TypeError","Message":"Argument 1 passed to OCA\TwoFactorU2F\Controller\SettingsController::finishRegister() must be of the type string, null given, called in /var/www/nextcloud/lib/private/AppFramework/Http/Dispatcher.php on line 170"

cogliostro avatar Nov 23 '20 10:11 cogliostro

This is not a server error https://github.com/nextcloud/twofactor_u2f/issues/789#issuecomment-732056807

ChristophWurst avatar Nov 24 '20 07:11 ChristophWurst

Check the browser console for the u2f error code

ChristophWurst avatar Nov 24 '20 07:11 ChristophWurst

I'm seeing the same errors in the console as @ahuemmer registered.

Uncaught (in promise) Error: U2F device registration failed (error code unknown) at a.rejectRegistration (AddDeviceDialog.vue:157) at AddDeviceDialog.vue:135

POST https://xfiles.nhn.no/apps/twofactor_u2f/settings/finishregister 500 (Internal Server Error)

[ERROR] twofactor_u2f: Error persisting registration {app: "twofactor_u2f", uid: "KENNETHV", config: {…}, request: XMLHttpRequest, response: {…}, …}

[ERROR] twofactor_u2f: Error: Server error while trying to complete U2F device registration {app: "twofactor_u2f", uid: "KENNETHV"}

cogliostro avatar Nov 24 '20 13:11 cogliostro

error code unknown

I guess we should add a console.error to https://github.com/nextcloud/twofactor_u2f/blob/27b330b5821e97cc1720172176a06a42cf4b6533/src/components/AddDeviceDialog.vue#L154-L159 so the original error is logged. Now it's impossible to find out what it was.

ChristophWurst avatar Nov 24 '20 13:11 ChristophWurst

For my case, I discover the error start happen on this callback

https://example.org/apps/twofactor_u2f/settings/startregister

there I get a json where the appId has the URL scheme as http:// even tho I'm doing a request from a valid https://. My server has a good setup on https, I could connect with desktop clients on my nextcloud installation and the overview said everything is clear and green, no error on https where I could see.

Now, I force it tho and push my id on client side (so browser, not PHP directly) to be https, it made the request well but then, when I'm about to save and store my data this next callback.

https://xample.org/apps/twofactor_u2f/settings/finishregister

Is where I stop, since the class on \OCA\TwoFactorU2F\Service\U2FManager::finishRegistration makes a call to \OCA\TwoFactorU2F\Service\U2FManager::getU2f

for some reason this code

	private function getU2f(): U2F {
		$url = $this->request->getServerProtocol() . '://' . $this->request->getServerHost();
		return new U2F($url);
	}

get the server protocol as http. I'm thinking is because my proxy server is behind a traefik reverse proxy where I call the port 80 on nginx and that pass it to the php-fpm as scheme http.

I'm going to force nginx to deliver the scheme https even on port 80 and come back with the result.

Hope this could provide some tracks on this matter.

killua99 avatar Jan 29 '21 20:01 killua99

Yes, this system variable that you could place on config.php did the trick

'overwriteprotocol'  => ' https' ,

Now the appId has https: and when making the request the Yubikey could be added without issue if your browser detect you are on a valid SSL Cert, the php backend just need to be tricked.

killua99 avatar Jan 29 '21 21:01 killua99

Thank you, @killua99, for your investigation! Unfortunately, this doesn't apply to my case, as I've always had the overwriteprotocol setting set to https as you suggested.

ahuemmer avatar Jan 30 '21 08:01 ahuemmer

Btw https://docs.nextcloud.com/server/stable/admin_manual/configuration_server/reverse_proxy_configuration.html is the docs page for reverse proxies if anyone wants to double-check their setups. That also covers the overwirteprotocol.

ChristophWurst avatar Feb 03 '21 18:02 ChristophWurst

@ChristophWurst Should i add a note in README letting users know to use https?

ashuio avatar May 20 '21 18:05 ashuio

Yes please :+1:

ChristophWurst avatar Jun 14 '21 06:06 ChristophWurst