Skip to content
This repository has been archived by the owner on Jan 8, 2024. It is now read-only.

Unable to add YubiKey U2F #725

Open
ahuemmer opened this issue Aug 14, 2020 · 16 comments
Open

Unable to add YubiKey U2F #725

ahuemmer opened this issue Aug 14, 2020 · 16 comments

Comments

@ahuemmer
Copy link

ahuemmer commented Aug 14, 2020

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!

@cogliostro
Copy link

Seeing the same problem on our installation running Nextcloud 19.0.5.

@ChristophWurst
Copy link
Member

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?

@cogliostro
Copy link

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

@cogliostro
Copy link

Also seems to work in Chrome.

@ChristophWurst
Copy link
Member

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?

@cogliostro
Copy link

"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"

@ChristophWurst
Copy link
Member

This is not a server error #789 (comment)

@ChristophWurst
Copy link
Member

Check the browser console for the u2f error code

@cogliostro
Copy link

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"}

@ChristophWurst
Copy link
Member

error code unknown

I guess we should add a console.error to

// 1 - OTHER_ERROR
// 2 - BAD_REQUEST
// 3 - CONFIGURATION_UNSUPPORTED
Promise.reject(new Error(t('twofactor_u2f', 'U2F device registration failed (error code {errorCode})', {
errorCode: data.errorCode || 'unknown'
})));
so the original error is logged. Now it's impossible to find out what it was.

@killua99
Copy link

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
Copy link

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.

@ahuemmer
Copy link
Author

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.

@ChristophWurst
Copy link
Member

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.

@ashuio
Copy link
Contributor

ashuio commented May 20, 2021

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

@ChristophWurst
Copy link
Member

Yes please 👍

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants