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

Add FIDO2 passwordless login support with security keys #16

Open
wants to merge 12 commits into
base: master
Choose a base branch
from

Conversation

petschekr
Copy link
Member

  • Adds support for logging in with FIDO2 security keys without a password 🎉
    • Test using a compatible security that can perform User Verification in addition to User Presence (i.e. YubiKey 5 series vs YubiKey 4 series)
  • Minor unrelated bug fixes
    • Logging in with [email protected] for the CAS now provides a better error message with log out link
    • Missing MIME types for static content have been added

@petschekr petschekr added the enhancement New feature or request label Aug 24, 2019
public readonly passportStrategy: Strategy;
private readonly timeout = 60000; // 60 seconds
private readonly fidoInstance = new Fido2Lib({
cryptoParams: [-7], // ECC only
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you document why this is -7

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok I find this weird too but it's a spec thing:

The alg is a number described in the COSE registry; for example, -7 indicates that the server accepts Elliptic Curve public keys using a SHA-256 signature algorithm

done(null, false, { "message": "Registration timed out. Please try again." });
return;
}
let email = session.email.trim().toLowerCase();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can we add a standard email sanitizer for all strategies?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good idea, will add

origin: createLink(request, "").slice(0, -1), // Removes trailing slash from origin
factor: "first",
publicKey: user.services.fido2.publicKey || "",
prevCounter: user.services.fido2.prevCounter || Number.MAX_SAFE_INTEGER,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why Number.MAX_SAFE_INTEGER?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The idea is that the counter prevents replay attacks because it must always be increasing. If we stored that the last auth was with counter set to 100, a replay of 100 or anything less than that will be rejected. If the prevCounter value is undefined or null for some reason, we set it to the maximum allowed number in JS so that the auth attempt will be rejected.

done(null, false, { "message": "Invalid session values" });
return;
}
if (Date.now() >= (session.fidoChallengeTime || 0) + this.timeout) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

move this logic to the top level of the passport callback since it's repeated?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good idea

@petschekr
Copy link
Member Author

Fun fact: Chrome on Android allegedly implements FIDO2 but cannot unlock the YubiKey due to a bug in Google Play Services (tracking issue I filed: https://bugs.chromium.org/p/chromium/issues/detail?id=997538) causing our site to reject the login attempt.

As I see it, we have two options:

  • Allow users to choose the security of their login (currently user verification with PIN is required but we could allow people to say they just want the less secure user presence test)
  • Require FIDO2 logins to have a fallback to another login method (possibly insecure, pain in the ass to implement, makes "passwordless" login not really passwordless)

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

Successfully merging this pull request may close these issues.

3 participants