Issues using passkeys with vaultwarden

I am a user of a self hosted discourse instance, I see the button to add passkeys. When I click my vaultwarden plugin opens up, to add it, but then I get a message

The passkey registration process either timed out, was cancelled or is not allowed."

I’m on firefox and already added passkeys, e.g. for GitHub, so it is working on firefox with vaultwarden but for some reason not in this particular discourse forum. I told the admins about and they said it is enabled (otherwise I would not see the add button, right?)


Hi Jappe,

Thanks for writing in. I have moved this into a separate topic since it’s a specific issue with Vaultwarden (who by the way, have their own Discourse forum :tada: ).

Do you know if this problem only happens with the Vaultwarden extension on Firefox? Have you tried other browsers?

If I were to test this, I’d need to set up a Vaultwarden server?


I think vaultvarden and the bitwarden firefox plugin is not the problem since passkey integration works with other services like GitHub.
I can also find this specific message in some yml file of discourse, which is indicating a not_allowed_error.

I don’t know, acutally it is the official bitwarden extension for firefox, but I use a self-hosted Vaultwarden instance.
I tried also firefox on Fedora, the initial problem occured on Firefox for Windows.
I will test now with Google Chrome on Windows.
Ok it also fails there, but I had a look into dev tools and found this:

Firefox console output
Content-Security-Policy: Die Einstellungen der Seite haben das Laden einer Ressource auf blob: blockiert ("img-src").

Object { jqXHR: {…}, textStatus: "error", errorThrown: "" }
errorThrown: ""
jqXHR: Object { readyState: 4, getResponseHeader: getResponseHeader(e), getAllResponseHeaders: getAllResponseHeaders(), … }
abort: function abort(e)
always: function always()
catch: function catch(e)
done: function add()
fail: function add()
getAllResponseHeaders: function getAllResponseHeaders()
getResponseHeader: function getResponseHeader(e)
jqTextStatus: "error"
overrideMimeType: function overrideMimeType(e)
pipe: function pipe()
progress: function add()
promise: function promise(e)
readyState: 4
requestedUrl: "/forum/u/register_passkey.json"
responseJSON: Object { errors: (1) […] }
responseText: '{"errors":["The origin of the authentication request does not match the server origin."]}'
setRequestHeader: function setRequestHeader(e, t)
state: function state()
status: 401
statusCode: function statusCode(e)
statusText: "error"
then: function then(e, n, i)
<prototype>: Object { … }
textStatus: "error"
<prototype>: Object { … }
__defineGetter__: function __defineGetter__()
__defineSetter__: function __defineSetter__()
__lookupGetter__: function __lookupGetter__()
__lookupSetter__: function __lookupSetter__()
constructor: function Object()
hasOwnProperty: function hasOwnProperty()
isPrototypeOf: function isPrototypeOf()
propertyIsEnumerable: function propertyIsEnumerable()
toLocaleString: function toLocaleString()
toString: function toString()
valueOf: function valueOf()
<get __proto__()>: function __proto__()
<set __proto__()>: function __proto__()

Quite the same on Chrome:

Failed to load resource: the server responded with a status of 401 ()
chunk.6d10396b901f5b95b67e.d41d8cd9.js:1 Object

So probably a server misconfig?

Yes, or use a provider. Bitwarden itself has a free tier for personal use.
I can also provide more info and testing if needed.

1 Like

Did some more testing:
I click the “Add” button, the popup appears and at this point I have already the error in the console from the createPasskey function.

Object { jqXHR: {…}, textStatus: "error", errorThrown: "" }

And then the acutal add to the vault fails, because there was no passkey created.

The first error message from the post before is probably not related to this problem, but to some CORS stuff on the dietpi server. The first error message about Content-Security-Policy originated from Dark-reader-extension)

1 Like

Yes, from the logs you posted, the main error message is this one:

The origin of the authentication request does not match the server origin.

Passkey and security key registration checks that the URL of the site making the registration matches between client (browser) and server. Most likely this instance has a mismatch, sometimes it’s http vs https, other times it’s proxies.

First thing I would check is whether the force https site setting is enabled.


Also, @JappeHallunken, just to rule out any general issues… can you add a passkey to your account here on meta?

1 Like

Yes, I could successfully add a passkey here on meta.

I will report this back! Thanks for your help.

First issue our end was CSP, not allowing blob: image sources. Now indeed there seems to be some setting missing/invalid, but I am not able to find it:

[AdminSidebar] Custom link root_admin_additional_root_admin_upgrade must have a valid I18n label, got admin.docker.upgrade_tab chunk.6d10396b901f5b95b67e.d41d8cd9.js:1:2588880

Object { jqXHR: {…}, textStatus: "error", errorThrown: "" }
errorThrown: ""
jqXHR: Object { readyState: 4, getResponseHeader: getResponseHeader(e), getAllResponseHeaders: getAllResponseHeaders()
, … }
textStatus: "error"
<prototype>: Object { … }

But I guess you are right and it is only a symptom of the 401.

HTTPS is enforced already via Cloudflare proxy and webserver redirect and also force https setting, HSTS, preloading etc, there is no way to ever access this Discourse instance via plain HTTP :wink:.

A problem might be that Discourse sits at /forum sub path, instead of at the root of the domain?


I think you may be right, the issue seems to be related to the subfoder setup. I’ll take a closer look at the code shortly.


I just merged FIX: Webauthn origin was incorrect for subfolder setups (#25651) · discourse/discourse@021a02c · GitHub, @MichaIng, can you give your site a rebuild and see if that fixes the issue?


Done. @JappeHallunken can you retry?


Yes, it’s working now, nice!
Thanks to everybody for solving this!