[DigitalPoint] Security & Passkeys

[DigitalPoint] Security & Passkeys 1.1.8

No permission to download
@digitalpoint
I am by no means a crypto expert, but doesn't
PHP:
$config['challenge'] = \XF::generateRandomString(32);
generate a weaker challenge (32 bytes "nonstandard base64" -> 192 bits entropy) vs. lbuchs\WebAuthn default code (32 bytes binary -> 256 bits entropy)?

It also seems like your code only supports ES256 but not RS256.


Relying Parties that wish to support a wide range of authenticators SHOULD include at least the following COSEAlgorithmIdentifier values:
  • -8 (Ed25519)
  • -7 (ES256)
  • -257 (RS256)

Ed25519 unfortunately isn't supported by the library (yet), but RS256 would work (yes, RSA is dead - might still be useful to have this available at least optionally?).
 
Last edited:
Yep, you aren't wrong... It's as good as someone's ability to guess 2^192 numbers in 900 seconds. So the attacker would need to be making about 6,974,557,483,762,983,000,000,000,000,000,000,000,000,000,000,000,000,000 HTTP requests per second to the server to cover all the possibilities in the 15 minute window that's allowed.

That being said, it's probably easier for them to simply try to guess the session cookie (which would have a larger window than 900 seconds and is also 192 bits).

Anything more than 32-bit is overkill for this, but I also don't care one way or the other, so I changed it to be 128 bytes. So next version will need an attacker making 1,725,020,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000 HTTP requests per second.

It's effectively equally impossible whether it's what it was (192 bits) or what I changed it to (768 bits). 🤷🏻‍♂️ Again, there's a hard time limit someone would have to "hack" it (900 seconds).

But ya... we'll see about Ed25519 in the future. Right now we are just talking about a draft proposal for a future version of WebAuthn (draft was published 11 days ago).
 
But ya... we'll see about Ed25519 in the future. Right now we are just talking about a draft proposal for a future version of WebAuthn (draft was published 11 days ago).
The recommendation for RPs to support Ed2559 is new, but the requirement for browsers to support this was already in Level 2, so any semi up to date browser should be able to handle this by now.

User agents MUST be able to return a non-null value for getPublicKey() when the credential public key has a COSEAlgorithmIdentifier value of:

  • -7 (ES256), where kty is 2 (with uncompressed points) and crv is 1 (P-256).
  • -257 (RS256).
  • -8 (EdDSA), where crv is 6 (Ed25519).
 
The recommendation for RPs to support Ed2559 is new, but the requirement for browsers to support this was already in Level 2, so any semi up to date browser should be able to handle this by now.
Well best way to get it supported if you need it would be to make a request with the author of the underlying library. I didn’t write it. 🤷🏻‍♂️
 
digitalpoint updated [DigitalPoint] Security & Passkeys with a new update entry:

Removed dependency on jQuery

  • Entropy for challenge changed from 192-bits to 768-bits
  • All JavaScript has been rewritten to be "native" (does not use jQuery) in preparation for removal of jQuery in XenForo 2.3.
If you aren't using XenForo 2.3, you don't need to upgrade (might be some unmeasurable speed increase [think nanoseconds] when running its JavaScript since it doesn't dip into...

Read the rest of this update entry...
 
Non-developer muggle type question here - If native Javascript is seemingly supported in addons pre-2.3, as opposed to jQuery - why is this such a big move for a lot of developers? Is it just preference in terms of developers using jQuery over native Javascript?

Like what you're doing - it doesn't seem like there are many barriers in terms of them readying and releasing further versions with native JS in place.
 
Non-developer muggle type question here - If native Javascript is seemingly supported in addons pre-2.3, as opposed to jQuery - why is this such a big move for a lot of developers? Is it just preference in terms of developers using jQuery over native Javascript?
Because when you have written a ton of JavaScript code, it's time consuming to go back and rewrite it all. An (small) example is this was written for jQuery:
JavaScript:
$(document).ready(function()
{
    $('#cfRange input').on('change', this.analytics.bind(this))
    $('#cfRange input:first-of-type').trigger('change');
}.bind(this));

To not use jQuery, it needs to be rewritten like so:
JavaScript:
document.addEventListener('DOMContentLoaded', () => {
	document.querySelectorAll('#cfRange input').forEach(
		(el) => {
			el.addEventListener('change', (e) => {
				this.analytics(e);
			});
		}
	);

	document.querySelector('#cfRange input').dispatchEvent(new Event('change'));
}, false);

The end result is the code is usually a little less simple (jQuery simplifies a lot of things for you), but it works without jQuery.

...so now scale that small rewrite times 1000 when you have a ton of JavaScript written for jQuery...
 
Because when you have written a ton of JavaScript code, it's time consuming to go back and rewrite it all. An (small) example is this was written for jQuery:
JavaScript:
$(document).ready(function()
{
    $('#cfRange input').on('change', this.analytics.bind(this))
    $('#cfRange input:first-of-type').trigger('change');
}.bind(this));

To not use jQuery, it needs to be rewritten like so:
JavaScript:
document.addEventListener('DOMContentLoaded', () => {
    document.querySelectorAll('#cfRange input').forEach(
        (el) => {
            el.addEventListener('change', (e) => {
                this.analytics(e);
            });
        }
    );

    document.querySelector('#cfRange input').dispatchEvent(new Event('change'));
}, false);

The end result is the code is usually a little less simple (jQuery simplifies a lot of things for you), but it works without jQuery.

...so now scale that small rewrite times 1000 when you have a ton of JavaScript written for jQuery...
So, often - in practice, writing jQuery is a lot faster (roughly 50% faster based on the line count alone above) than JS. Despite the way this is going with XF - As a developer, do you think going this direction is the best direction? Like - Does it make sense?

Just interested is all. The payoff seems to be for the end user as a whole, and I guess that's the most important thing.
 
So, often - in practice, writing jQuery is a lot faster (roughly 50% faster based on the line count alone above) than JS. Despite the way this is going with XF - As a developer, do you think going this direction is the best direction? Like - Does it make sense?

Just interested is all. The payoff seems to be for the end user as a whole, and I guess that's the most important thing.
Ya, it probably makes sense today. It didn't make sense years ago when you were needing to do different things for different browsers... But browsers are now (fairly) consistent across the board when it comes to JavaScript stuff. Back then, jQuery was a tool to so you could write code once and jQuery handled the browser-specific intricacies, but that's just not needed anymore. So now jQuery is more of a crutch for those that don't want to write "real" JavaScript vs. what it original was intended for (handling browser intricacies). So is the overhead of downloading an running a fairly large library (jQuery) worth developers being lazy? IMO, no... anytime you can cut bloat, it's good in my book.

It also got me thinking about some non-XenForo projects I have. Like I'm probably going to rewrite some JavaScript I have in WordPress plugins even though WordPress isn't deprecating jQuery. Better to not have to rely on 3rd party libraries for things if there's no real reason to any longer.
 
Ya, it probably makes sense today. It didn't make sense years ago when you were needing to do different things for different browsers... But browsers are now (fairly) consistent across the board when it comes to JavaScript stuff. Back then, jQuery was a tool to so you could write code once and jQuery handled the browser-specific intricacies, but that's just not needed anymore. So now jQuery is more of a crutch for those that don't want to write "real" JavaScript vs. what it original was intended for (handling browser intricacies). So is the overhead of downloading an running a fairly large library (jQuery) worth developers being lazy? IMO, no... anytime you can cut bloat, it's good in my book.

It also got me thinking about some non-XenForo projects I have. Like I'm probably going to rewrite some JavaScript I have in WordPress plugins even though WordPress isn't deprecating jQuery. Better to not have to rely on 3rd party libraries for things if there's no real reason to any longer.
Makes sense. It's for the better and a necessary change then.

Out of interest, I just sent your original jQuery code through Bing AI and asked it to convert to JS. This is the output -

JavaScript:
document.addEventListener("DOMContentLoaded", function() {
    var inputs = document.querySelectorAll('#cfRange input');
    for (var i = 0; i < inputs.length; i++) {
        inputs[i].addEventListener('change', this.analytics.bind(this));
    }
    inputs[0].dispatchEvent(new Event('change'));
}.bind(this));

Mostly different. Not sure if this would be valid or work? It provides an explanation, too -

'This code does the same thing as your jQuery code. It waits for the document to load, then it adds an ‘change’ event listener to each input element within the element with the id ‘cfRange’. It also triggers the ‘change’ event on the first input element within ‘cfRange’.'

:p
 
Makes sense. It's for the better and a necessary change then.

Out of interest, I just sent your original jQuery code through Bing AI and asked it to convert to JS. This is the output -

JavaScript:
document.addEventListener("DOMContentLoaded", function() {
    var inputs = document.querySelectorAll('#cfRange input');
    for (var i = 0; i < inputs.length; i++) {
        inputs[i].addEventListener('change', this.analytics.bind(this));
    }
    inputs[0].dispatchEvent(new Event('change'));
}.bind(this));

Mostly different. Not sure if this would be valid or work? It provides an explanation, too -

'This code does the same thing as your jQuery code. It waits for the document to load, then it adds an ‘change’ event listener to each input element within the element with the id ‘cfRange’. It also triggers the ‘change’ event on the first input element within ‘cfRange’.'

:p
Ya, there are different ways it could be done. Since I'm rewriting code anyway, I'm also migrating to the newer arrow functions in JavaScript vs. anonymous functions because the scoping and needing to do .bind(this) gets really convoluted and annoying when dealing with large classes. I'm also not a big fan of writing to variables for no reason other than to make the overall code smaller. The closure compiler that turns human readable JavaScript into minified versions handles all that for you if needed (that's why I'm not dumping everything into input variable and looping through that) and in the end (what users are downloading) ends up being the same either way.
 
Screenshot_20230928_205016_Google Play services.webp
For some reason, I am on 1.1.7, and I enabled passkey support via 1password, it is not giving me an option for the passkey that I just created on my own site.

Is this a XenForo issue? A add-on issue? Or a 1password issue?
 
Not sure… can you disable 1password and see if it works as expected? I don’t know anything about 1password or what it’s doing.
 
If I turn off 1Password, it won't prompt at all. It's a software solution for Passkeys and Passwords at same time. The Passkey is connected to 1pass and won't work at all without it. Doesn't even prompt to use the passkey and I have to use the old-school method.

1password is one of the most secure password managers out there. It has never been breached in a hack attempt. It uses basically 2 or 3 passwords to add the app to a new device, then just the one master to remember.
 
As long as 1password supports WebAuthn/FIDO2, it should work (it’s just a standard protocol). Although I would think it needs to be supported by the browser itself rather than an app since the browser is doing the underlying “stuff”.

What browser/version are you using?
 
As long as 1password supports WebAuthn/FIDO2, it should work (it’s just a standard protocol). Although I would think it needs to be supported by the browser itself rather than an app since the browser is doing the underlying “stuff”.

What browser/version are you using?
MS Edge for Android. Current build (dunno its numbers)
 
Everything I read says Edge on Android doesn’t yet support passkeys and 1Password sort of supports it for some things but it’s beta.

Are you able to try a different browser that definitely supports it just as a test (for example Chrome)?

There’s nothing I can do on my end to make a certain browser support passkeys faster. It’s simply a web standard that a browser either supports or it doesn’t (like you can’t make a browser support HTTP/3 magically). There is no browser specific code to make WebAuthn/FIDO2 work or change how an individual browser allows for it.
 
Top Bottom