Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Not posible to store a YubiKey OTP in the user Account Settings #3003

Closed
zucht opened this issue Dec 17, 2022 · 16 comments · Fixed by #3059
Closed

Not posible to store a YubiKey OTP in the user Account Settings #3003

zucht opened this issue Dec 17, 2022 · 16 comments · Fixed by #3059
Assignees
Labels
enhancement New feature or request good first issue Good for newcomers

Comments

@zucht
Copy link

zucht commented Dec 17, 2022

Subject of the issue

After following the steps in the Vaultwarden Wiki how to obtain a Client ID and Secret Key at Yubico and setting those values as enviromental variables for the docker container (https://github.com/dani-garcia/vaultwarden/wiki/Enabling-Yubikey-OTP-authentication) I still can't register any YubKey in Vaultwarden. When trying to do so, after touching the gold contact of the YubiKey at one of the YubiKey fields in user account settings, an red error notification is given:

Invalid YubiKey OTP provided.

Tested it with multiple YubiKey Keys (2x YubiKey 5 NFC and 2x YubiKey 5C NFC)

The error is also logged in the logfile:

[2022-12-17 12:46:21.330][request][INFO] PUT /api/two-factor/yubikey
[2022-12-17 12:46:21.402][error][ERROR] Invalid Yubikey OTP provided.
[CAUSE] Network(
    reqwest::Error {
        kind: Builder,
        source: RelativeUrlWithoutBase,
    },
)
[2022-12-17 12:46:21.403][response][INFO] (activate_yubikey_put) PUT /api/two-factor/yubikey => 400 Bad Request

The YubiKey OTP DEMO site validates all my keys successful:

{
  "otp": "xxx",
  "nonce": "xxx",
  "serial": xxx,
  "sl": "100",
  "status": "OK",
  "t": "2022-12-17T12:51:00Z0068"
}

I've found the given error in the source code of yubikey.rs at an if/then statement at line 150. The statement looks to accept a string of which the total length is only 12 characters long, while in fact a YubiKey is a 44 character long string where the first 12 characters remain constant (https://developers.yubico.com/OTP/OTPs_Explained.html).

If I for testing purposes only enter the first 12 characters of my YubiKey in the field, the value is stored at the settings. Only this will cause YubiKey 2FA login for Vaultwarden to always fail.

Deployment environment

Your environment (Generated via diagnostics page)

  • Vaultwarden version: v1.26.0
  • Web-vault version: v2022.10.0
  • Running within Docker: true (Base: Alpine)
  • Environment settings overridden: true
  • Uses a reverse proxy: true
  • IP Header check: true (X-Forwarded-For)
  • Internet access: true
  • Internet access via a proxy: false
  • DNS Check: true
  • Time Check: true
  • Domain Configuration Check: true
  • HTTPS Check: true
  • Database type: SQLite
  • Database version: 3.35.4
  • Clients used:
  • Reverse proxy and version:
  • Other relevant information:

Config (Generated via diagnostics page)

Show Running Config

Environment settings which are overridden: DOMAIN, SIGNUPS_ALLOWED, SHOW_PASSWORD_HINT, ADMIN_TOKEN, IP_HEADER, YUBICO_CLIENT_ID, YUBICO_SECRET_KEY, SMTP_HOST, SMTP_SECURITY, SMTP_PORT, SMTP_FROM, SMTP_FROM_NAME, SMTP_USERNAME, SMTP_PASSWORD

{
  "_duo_akey": "***",
  "_enable_duo": true,
  "_enable_email_2fa": true,
  "_enable_smtp": true,
  "_enable_yubico": true,
  "_icon_service_csp": "",
  "_icon_service_url": "",
  "_ip_header_enabled": true,
  "admin_ratelimit_max_burst": 3,
  "admin_ratelimit_seconds": 300,
  "admin_token": "***",
  "allowed_iframe_ancestors": "",
  "attachments_folder": "data/attachments",
  "authenticator_disable_time_drift": false,
  "data_folder": "data",
  "database_conn_init": "",
  "database_max_conns": 10,
  "database_timeout": 30,
  "database_url": "****/**.*******",
  "db_connection_retries": 15,
  "disable_2fa_remember": false,
  "disable_admin_token": false,
  "disable_icon_download": false,
  "domain": "*****://*********.*****.**",
  "domain_origin": "*****://*********.*****.**",
  "domain_path": "",
  "domain_set": true,
  "duo_host": "***",
  "duo_ikey": "***",
  "duo_skey": "***",
  "email_attempts_limit": 3,
  "email_expiration_time": 600,
  "email_token_size": 6,
  "emergency_access_allowed": true,
  "emergency_notification_reminder_schedule": "0 5 * * * *",
  "emergency_request_timeout_schedule": "0 5 * * * *",
  "enable_db_wal": true,
  "extended_logging": true,
  "helo_name": null,
  "hibp_api_key": null,
  "icon_blacklist_non_global_ips": true,
  "icon_blacklist_regex": null,
  "icon_cache_folder": "data/icon_cache",
  "icon_cache_negttl": 259200,
  "icon_cache_ttl": 2592000,
  "icon_download_timeout": 10,
  "icon_redirect_code": 302,
  "icon_service": "internal",
  "incomplete_2fa_schedule": "30 * * * * *",
  "incomplete_2fa_time_limit": 3,
  "invitation_expiration_hours": 120,
  "invitation_org_name": "Bitwarden",
  "invitations_allowed": true,
  "ip_header": "X-Forwarded-For",
  "job_poll_interval_ms": 30000,
  "log_file": "/data/bitwarden.log",
  "log_level": "Info",
  "log_timestamp_format": "%Y-%m-%d %H:%M:%S.%3f",
  "login_ratelimit_max_burst": 10,
  "login_ratelimit_seconds": 60,
  "org_attachment_limit": null,
  "org_creation_users": "",
  "password_hints_allowed": true,
  "password_iterations": 100000,
  "reload_templates": false,
  "require_device_email": false,
  "rsa_key_filename": "data/rsa_key",
  "send_purge_schedule": "0 5 * * * *",
  "sends_allowed": true,
  "sends_folder": "data/sends",
  "show_password_hint": false,
  "signups_allowed": false,
  "signups_domains_whitelist": "",
  "signups_verify": true,
  "signups_verify_resend_limit": 6,
  "signups_verify_resend_time": 3600,
  "smtp_accept_invalid_certs": false,
  "smtp_accept_invalid_hostnames": false,
  "smtp_auth_mechanism": null,
  "smtp_debug": false,
  "smtp_explicit_tls": null,
  "smtp_from": "*******@*****.***",
  "smtp_from_name": "***",
  "smtp_host": "****.*****.***",
  "smtp_password": "***",
  "smtp_port": 587,
  "smtp_security": "starttls",
  "smtp_ssl": null,
  "smtp_timeout": 15,
  "smtp_username": "*******",
  "templates_folder": "data/templates",
  "tmp_folder": "data/tmp",
  "trash_auto_delete_days": null,
  "trash_purge_schedule": "0 5 0 * * *",
  "use_syslog": false,
  "user_attachment_limit": null,
  "web_vault_enabled": true,
  "web_vault_folder": "web-vault/",
  "websocket_address": "0.0.0.0",
  "websocket_enabled": true,
  "websocket_port": 3012,
  "yubico_client_id": "***",
  "yubico_secret_key": "***",
  "yubico_server": ""
}

Steps to reproduce

  1. Follow steps "Enabling Yubikey OTP authentication" in Vaultwarden Wiki.
  2. After login in at the Bitwarden Web Vault go to Account Settings.
  3. Select Security > Two-step login > YubiKey OTP Security Key > Manage.
  4. Enter Master Password and click Continue.
  5. Hilight the first YukiKey 1 field, insert the YubiKey and press the gold contact of the YubiKey.

Expected behaviour

Posible to store the YubiKey's as 2FA for Vaultwarden at the user account settings by just touching the gold contact.

Actual behaviour

Not posible to use YubiKey as MFA in Vaultwarden.

Troubleshooting data

20221204

@BlackDex
Copy link
Collaborator

Did you also tried Webauthn? And what are the results if you try that method?

If i understand you correctly, the key sent is larger then the 12 we currently expect, and that is because it is sending the full key and not only the identifier right?

Have you tried using an other browser or client?
Could you maybe also try if the testing tagged release makes any difference?

@zucht
Copy link
Author

zucht commented Dec 18, 2022

With the exception of NFC WebAuthn works for the YubiKeys.

You are right. The first 12 characters are the Public Key of the YubiKey where the last 32 characters are a unique passcode and a counter. The way described how to register a YubiKey is the way it works in Bitwarden if you have a Premium subscription.

I've tested several browsers all with the same outcome (Opera, Firefox and Chrome).

The testing tag doesn't change the behaviour or error's in the log.

@Blacks-Army
Copy link

Blacks-Army commented Dec 18, 2022

Change your DNS Server to Cloudflares or something else (On your Hosting Server), just don't use your local one like Adguard Home or PiHole. Had the same Problem that solved it for me!

@zucht
Copy link
Author

zucht commented Dec 18, 2022

No funky DNS adguard/blocking on my hosted VPS, thanks anyway for your suggestion. Anyhow this give me some food for thought and in the mean time I'm started to setup another test VPS.

@BlackDex
Copy link
Collaborator

BlackDex commented Dec 18, 2022

@zucht, could you tell me if there are panics in the logs during the register of the code.
Or, when you register the key with only the identifier (12 chars), and later try to login using that?
Because, i think i have found the culprit here by using a fake (software based) yubikey which also doesn't work.

Update:
I just tested it with the current latest release, and it isn't an issue there. I can use my fake yubikey just fine, during register and login. The issue i encountered seems to be something with an updated library i think.

@BlackDex
Copy link
Collaborator

I just tested it some more, but it does seem to work for me just fine.
Are you sure you have followed the correct way to register your key?
https://github.com/dani-garcia/vaultwarden/wiki/Enabling-Yubikey-OTP-authentication

First register your key here: https://upload.yubico.com/
And afterwards generate the correct id/key for using the API via here https://upgrade.yubico.com/getapikey/ ?

That seems to work just fine for me.

@monkeybape
Copy link

same problem

@BlackDex
Copy link
Collaborator

same problem

@monkeybape , could you test with the testing tagged release please?
And enable at least LOG_LEVEL=debug and try again.

Also, make sure everything is fine according to the /admin/diagnostics page like domain, time etc...
We would like to have the logs from the point you press the submit button to add a new key.

Same btw for @zucht .
There are some changes in the current testing tagged version (released yesterday) which might help, but not sure.

@zucht
Copy link
Author

zucht commented Dec 19, 2022

Hi @BlackDex

I did all your suggested steps but without success.

Just to be sure, before starting these steps, I've even reset the OTP field of one of my spare YubiKey's with the YubiKey Personalisation Tool. This also means I've uploaded the newly generated OTP to Yubico and generated a new API Client ID and Secret Key with the use of this new OTP.

These variables are used in the test Vaultwarden testing branch setup where debug logging is enabled.

@zucht, could you tell me if there are panics in the logs during the register of the code. Or, when you register the key with only the identifier (12 chars), and later try to login using that? Because, i think i have found the culprit here by using a fake (software based) yubikey which also doesn't work.

No panics in the log whatsoever. I can save the OTP in Vaultwarden if I only enter the Public Key (so the first 12 characters). Unfortunately when logging back in at a separate incognito screen the YubiKey OTP isn't accepted when pressing the contact of the key.

Before uploading the log I need to sanitize it by redacting some personal/private information. I will upload it ASAP, please bear with me!

Some timestamps (CET) in advance:

[2022-12-19 19:30:08.973] - Trying to store a YubiKey by pressing the contact.
[2022-12-19 19:30:44.346] - Storing only the Public Key (first 12 characters) of YubiKey.
[2022-12-19 19:31:10.103] - 2FA Login failed with stored Public Key.

Your environment (Generated via diagnostics page)

  • Vaultwarden version: v1.26.0-10dadfca
  • Web-vault version: v2022.12.0
  • Running within Docker: true (Base: Debian)
  • Environment settings overridden: false
  • Uses a reverse proxy: true
  • IP Header check: true (X-Forwarded-For)
  • Internet access: true
  • Internet access via a proxy: false
  • DNS Check: true
  • Time Check: true
  • Domain Configuration Check: true
  • HTTPS Check: true
  • Database type: SQLite
  • Database version: 3.39.2
  • Clients used:
  • Reverse proxy and version:
  • Other relevant information:

Config (Generated via diagnostics page)

Show Running Config

Environment settings which are overridden:

{
  "_duo_akey": null,
  "_enable_duo": false,
  "_enable_email_2fa": true,
  "_enable_smtp": true,
  "_enable_yubico": true,
  "_icon_service_csp": "",
  "_icon_service_url": "",
  "_ip_header_enabled": true,
  "_smtp_img_src": "cid:",
  "admin_ratelimit_max_burst": 3,
  "admin_ratelimit_seconds": 300,
  "admin_token": "***",
  "allowed_iframe_ancestors": "",
  "attachments_folder": "data/attachments",
  "authenticator_disable_time_drift": false,
  "data_folder": "data",
  "database_conn_init": "",
  "database_max_conns": 10,
  "database_timeout": 30,
  "database_url": "***************",
  "db_connection_retries": 15,
  "disable_2fa_remember": false,
  "disable_admin_token": false,
  "disable_icon_download": false,
  "domain": "*****://*************",
  "domain_origin": "*****://*************",
  "domain_path": "",
  "domain_set": true,
  "duo_host": null,
  "duo_ikey": null,
  "duo_skey": null,
  "email_attempts_limit": 3,
  "email_expiration_time": 600,
  "email_token_size": 6,
  "emergency_access_allowed": true,
  "emergency_notification_reminder_schedule": "0 3 * * * *",
  "emergency_request_timeout_schedule": "0 7 * * * *",
  "enable_db_wal": true,
  "event_cleanup_schedule": "0 10 0 * * *",
  "events_days_retain": null,
  "extended_logging": true,
  "helo_name": null,
  "hibp_api_key": null,
  "icon_blacklist_non_global_ips": true,
  "icon_blacklist_regex": null,
  "icon_cache_folder": "data/icon_cache",
  "icon_cache_negttl": 259200,
  "icon_cache_ttl": 2592000,
  "icon_download_timeout": 10,
  "icon_redirect_code": 302,
  "icon_service": "internal",
  "incomplete_2fa_schedule": "30 * * * * *",
  "incomplete_2fa_time_limit": 3,
  "invitation_expiration_hours": 120,
  "invitation_org_name": "Vaultwarden",
  "invitations_allowed": true,
  "ip_header": "X-Forwarded-For",
  "job_poll_interval_ms": 30000,
  "log_file": "/data/vaultwarden.log",
  "log_level": "debug",
  "log_timestamp_format": "%Y-%m-%d %H:%M:%S.%3f",
  "login_ratelimit_max_burst": 10,
  "login_ratelimit_seconds": 60,
  "org_attachment_limit": null,
  "org_creation_users": "",
  "org_events_enabled": false,
  "org_groups_enabled": false,
  "password_hints_allowed": true,
  "password_iterations": 100000,
  "reload_templates": false,
  "require_device_email": false,
  "rsa_key_filename": "data/rsa_key",
  "send_purge_schedule": "0 5 * * * *",
  "sends_allowed": true,
  "sends_folder": "data/sends",
  "show_password_hint": false,
  "signups_allowed": false,
  "signups_domains_whitelist": "",
  "signups_verify": false,
  "signups_verify_resend_limit": 6,
  "signups_verify_resend_time": 3600,
  "smtp_accept_invalid_certs": false,
  "smtp_accept_invalid_hostnames": false,
  "smtp_auth_mechanism": null,
  "smtp_debug": false,
  "smtp_embed_images": true,
  "smtp_explicit_tls": null,
  "smtp_from": "*****************",
  "smtp_from_name": "***)",
  "smtp_host": "**************",
  "smtp_password": "***",
  "smtp_port": 587,
  "smtp_security": "starttls",
  "smtp_ssl": null,
  "smtp_timeout": 15,
  "smtp_username": "*******",
  "templates_folder": "data/templates",
  "tmp_folder": "data/tmp",
  "trash_auto_delete_days": null,
  "trash_purge_schedule": "0 5 0 * * *",
  "use_syslog": false,
  "user_attachment_limit": null,
  "web_vault_enabled": true,
  "web_vault_folder": "web-vault/",
  "websocket_address": "0.0.0.0",
  "websocket_enabled": true,
  "websocket_port": 3012,
  "yubico_client_id": "***",
  "yubico_secret_key": "***",
  "yubico_server": ""
}

@BlackDex
Copy link
Collaborator

BlackDex commented Dec 19, 2022

@zucht this looks like a DNS issue to me.
Could you provide the logs from the moment the call comes in?
It should also generate dns logs during that call.

All this btw using the full key, not just the 12 first chars.

@BlackDex
Copy link
Collaborator

@zucht @monkeybape, I'm not able reproduce this at all.
I tried breaking the DNS, that resulted in other errors.

The only way I'm able to break this which kinda looks like this, is providing a wrong YUBICO_CLIENT_ID.

Please be sure to provide the correct YUBICO_CLIENT_ID and corresponding YUBICO_SECRET_KEY which are provided after filling in the form here: https://upgrade.yubico.com/getapikey/

Also, if this still happens, we need some logs. I'm just not able to reproduce this in any way.

@BlackDex BlackDex added the troubleshooting There might be bug or it could be user error, more info needed label Dec 20, 2022
@zucht
Copy link
Author

zucht commented Dec 24, 2022

@BlackDex:
I test diffrent generated YUBICO_CLIENT_ID, diffrent VPS (Google and Oracle) and setup my docker-compose.yml with and without the DNS option that pointed to Cloudflare/Google DNS. All without success.

Here is a pastebin: https://privatebin.net/?05e023830f09617c#Cr57YnPYh87tednNsB9upDKpFcFqqubDfKkYRT9xP2AK

@BlackDex
Copy link
Collaborator

BlackDex commented Dec 24, 2022

Looking at this error, and your support string, I think i know the issue.
You seem to have yubico_server configured, although it's an empty string, it is defined, and now that empty string is used as an url to contact yubico. Try to remove/unset that variable and check again.

Also, in the support string it should say null as a value

We do need to catch these items, because that variable should be a valid url of course.

[2022-12-19 19:30:08.997][error][ERROR] Invalid Yubikey OTP provided.
[CAUSE] Network(
    reqwest::Error {
        kind: Builder,
        source: RelativeUrlWithoutBase,
    },
)

@BlackDex BlackDex added the enhancement New feature or request label Dec 24, 2022
@zucht
Copy link
Author

zucht commented Dec 24, 2022

Thanks @BlackDex, removing YUBICO_SERVER did fix the issue!

@BlackDex
Copy link
Collaborator

Cool. Good to know. I'll leave this ticket open so we will be reminded to fix/check that parameter to be a valid URI.

@BlackDex BlackDex added good first issue Good for newcomers and removed troubleshooting There might be bug or it could be user error, more info needed labels Dec 25, 2022
BlackDex added a commit to BlackDex/vaultwarden that referenced this issue Dec 28, 2022
If the `YUBICO_SERVER` is defined to an empty string, the whole yubikey
implementation doesn't work anymore.

This PR adds a check for this variable that it at least starts with `https://`.

Resolves dani-garcia#3003
@BlackDex BlackDex self-assigned this Jan 3, 2023
dani-garcia pushed a commit that referenced this issue Jan 9, 2023
If the `YUBICO_SERVER` is defined to an empty string, the whole yubikey
implementation doesn't work anymore.

This PR adds a check for this variable that it at least starts with `https://`.

Resolves #3003
dani-garcia pushed a commit that referenced this issue Jan 9, 2023
If the `YUBICO_SERVER` is defined to an empty string, the whole yubikey
implementation doesn't work anymore.

This PR adds a check for this variable that it at least starts with `https://`.

Resolves #3003
dani-garcia pushed a commit that referenced this issue Jan 9, 2023
If the `YUBICO_SERVER` is defined to an empty string, the whole yubikey
implementation doesn't work anymore.

This PR adds a check for this variable that it at least starts with `https://`.

Resolves #3003
dani-garcia pushed a commit that referenced this issue Jan 9, 2023
If the `YUBICO_SERVER` is defined to an empty string, the whole yubikey
implementation doesn't work anymore.

This PR adds a check for this variable that it at least starts with `https://`.

Resolves #3003
dani-garcia pushed a commit that referenced this issue Jan 9, 2023
If the `YUBICO_SERVER` is defined to an empty string, the whole yubikey
implementation doesn't work anymore.

This PR adds a check for this variable that it at least starts with `https://`.

Resolves #3003
dani-garcia pushed a commit that referenced this issue Jan 9, 2023
If the `YUBICO_SERVER` is defined to an empty string, the whole yubikey
implementation doesn't work anymore.

This PR adds a check for this variable that it at least starts with `https://`.

Resolves #3003
@Shurov
Copy link

Shurov commented Jun 5, 2023

You seem to have yubico_server configured, although it's an empty string, it is defined, and now that empty string is used as an url to contact yubico.

I had it non-empty - it was filled with mydomain, as per instructions, so instructions are a bit misleading (mydomain vs yubico servers). Removing the whole env_var helped though

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request good first issue Good for newcomers
Projects
None yet
Development

Successfully merging a pull request may close this issue.

5 participants