scheb / 2fa

Two-factor authentication for Symfony applications šŸ”
MIT License
492 stars 72 forks source link

Support hardware tokens (WebAuthn) #25

Open stephanvierkant opened 3 years ago

stephanvierkant commented 3 years ago

I'm using hardware tokens from Yubico. It would be great if this library supports WebAuthn.

I've used r/u2f-two-factor-bundle before, but it doesn't support scheb/2fa and it lacks some quality this library has. And I've think it's better to support the newer WebAuthn API instead of FIDO2/U2F.

See https://caniuse.com/webauthn for browser support.

Spomky commented 3 years ago

Hi @stephanvierkant,

Actually I started to develop an extension to that lib to support Webauthn. It is based on the web-auth/* framework I manage. Unfortunately my planning has not allowed me to spend much time so farā€¦ but this is still in my todo list.

By the way, it will allow hardware tokens (Yubico, Feitianā€¦) as well as internal authenticator (Android, Apple Face/TouchIdā€¦).

stephanvierkant commented 3 years ago

Great to hear! Keep us posted and let us know if you need some help.

scheb commented 3 years ago

I have to say I have no experience at all with hardware token (no idea what FIDO2/U2F is), so I'm probably not the best person to implement this.

Why not contribute back to r/u2f-two-factor-bundle to improve the library?

scheb commented 3 years ago

Flagging this with "help wanted", if this should ever become part of the 2fa package and not being provided by a 3rd-party package. Someone with knowledge in that field, who knows how it's best implemented, what libraries to use, etc. would be needed to contribute it. As mentioned above, I'm feeling myself not experienced enough with that authentication method to implement it with confidence.

PhilETaylor commented 3 years ago

Flagging this with "help wanted"

I think its time I contributed back ;-) drop me a quick email at phil@phil-taylor.com and I'll reply back with my thoughts on a plan.

wouterj commented 3 years ago

I have been playing with the web-auth/* packages and webauthn (using the Krypton app, as I don't have a physical key) before.

From my findings, the best solution would be to create a two factor provider implementation using this package (or at least, webauthn is way to complex to implement without third party package). So I would suggest to either create a two factor provider for web-auth/webauthn-framework in this bundle or someone contribute an implementation of TwoFactorProviderInterface to https://github.com/web-auth/webauthn-symfony-bundle

Spomky commented 3 years ago

Hi @wouterj,

web-auth/* packages author here. I have started working on a two factor provider, but haven't found much time so far. I will try to propose a draft PR this week so that we can start working on that.

wouterj commented 3 years ago

Yes, no need to rush. Someone on twitter proposed this idea and I just wanted to quickly share my thoughts on this, in case someone wants to work on it but needs some directions :)

scheb commented 3 years ago

I've also had a email exchange with @PhilETaylor recently, though haven't heard back from him. He mentioned that he has some implementations ready, that he could contribute.

dkarlovi commented 3 years ago

@wouterj what's the use case here? Use webauthn instead of TOTP (as in, no auth codes, use a Yubikey or fingerprint on mobile)?

scheb commented 3 years ago

The use case is to provide another common two-factor authentication method as a ready-to-use package, besides the 3 that the bundle already supports (TOTP, Google Authenticator, Code-via-Email).

Spomky commented 3 years ago

In addition to the @scheb answer, Webauthn can be used as new auth factor, but offers more than that. When your users already registered (at least) one authenticator, they can directly be logged in without password (and without username under certain requirements). Moreover,contrary to TOTP, email or SMS, with Webauthn you don't store are secret or sensitive data (phone number, e-mail address, shared secret...). No matter if the database is hacked. No need for an extra application or to quit the current website. Everithing is done through the API with hardware tokens or trusted platform modules (TPM). The latter is already working for Android, Windows Hello and MacOS.

PhilETaylor commented 3 years ago

I spent considerable time on this, but got pulled away (as is life) sorry. Also with scheb not having experience with webauth I thought I would struggle to get something past the line.

We already have scheb/2fa or webauth login at manage.mySites.guru but its not currently implemented as a another common two-factor authentication method as a ready-to-use package

It would be relatively easy to replicate the other providers, however the difference to the existing flow is that there is an initial ajax call needed after the user has provided their username (credential identifier) to get the current stored webauth data for that user, before the third party lib js can provide the challenge prompt in the browser.

Currently you have LOGIN FORM COMPLETE -> SUBMIT -> ENTER 2FA CODE -> SUBMIT -> LOGGED IN

With webauthn this would be: LOGIN FORM USERNAME, ajax call, prompt to "touch/activate" key, ajax call -> AUTO SUBMIT -> LOGGED IN

I think, for the scheb/2fa implementation, the additional/advanced features of webauthn (like login without username) should be ignored (At least initially), and have the scheb/2fa implementation be just true to the name, "two factor auth".

I think we should financially gift a hardware key to @scheb so that he can hold it in his hand, and start to understand it. Send me a amazon gift list or link :)

As has been said before, no one should ever consider doing any of this without @Spomky `web-auth/* libs ;-)

dkarlovi commented 3 years ago

no one should ever consider doing any of this without @Spomky `web-auth/* libs

Fully agreed here, the protocol seems way too thick to inline it here or anywhere. Having a common implementation which gets used (in 2FA scenarios or directly) is the best approach for the entire ecosystem IMO.

PhilETaylor commented 3 years ago

Joomla 4.0.0 Stable just released has webauthn now, and their approach (as is mine on my service) is to have two buttons on the login form one for using a password, and one for using webauthn (so no need to enter password), I still think this is confusing, but this is the major difference to the way all the other providers work (they all take you to a captive 2fa code entry page after providing username/password)

Joomla 4 Login

Screenshot 2021-08-23 at 13 44 04

My Login

Screenshot 2021-08-23 at 13 44 41
Spomky commented 3 years ago

Hi there,

TL;DR: I must admit that @PhilETaylor is right: this requires too much modification and I prefer another approach.

As said earlier, I started working on a fork of this project in order to add a new 2nd factor named webauthn. While coding, I realized it adds too much complexity on the user entity and requires lots of classes that duplicate the webauthn library (routing, controllers).

The approach proposed by Joomla could seem to be confusing, but for me it is not.

For some professional projects I manage, we use Auth0 and the Universal Login is quite similar (source: https://cdn.auth0.com/manhattan/versions/1.3361.0/assets/auth-profiles/identifier-first-biometrics.svg): Auth0 Authentication Flow

My conclusion is that adding a new 2nd factor will cause headaches while just adding the dedicated Webauthn is (relatively) simple. The main problem is that the Webauthn security bundle does not support the new Symfony authentication process. So for now, I prefer to take time supporting that new feature. Hoping you understand that choice.

Spomky commented 3 years ago

I have been playing with the web-auth/* packages and webauthn (using the Krypton app, as I don't have a physical key) before.

@wouterj, I received some authenticators from a manufacturer for the Stefen Richter participation at SF Paris 2020. I still have one or two if needed.

scheb commented 3 years ago

From what I've learned so far, WebAuthn is much more capable than just providing another authentication code in a 2fa process.

Though, I'd like to scope the discussion here around providing a second-factor authentication code within a multi-step authentication process. This second step would be completely independent from how user was initially authenticated (may it be username+passwort or something else). The goal would be to exeucte this second step via WebAuthn API, basically instead of typing an authentication code manually.

If you'd want to do user identification and authentication through WebAuthn, then you're not doing 2-step-authentication, but you're doing single-step authentication. That's something Symfony Security can do out-of-the-box, you don't need 2fa-bundle for that. As far as I understand, that's exactly what web-auth/webauthn-symfony-bundle is providing (@Spomky correct me if I'm wrong on that), so if that's your use-case, just use that other bundle.

Anyone who's looking for WebAuthn support as a second-factor authentication code within a multi-step authentication process, feel free to add to the discussion and contribute. But maybe web-auth/webauthn-symfony-bundle is actually what you want ;)


The main problem is that the Webauthn security bundle does not support the new Symfony authentication process. So for now, I prefer to take time supporting that new feature. Hoping you understand that choice.

@Spomky If you need help with that, let me know.

wouterj commented 3 years ago

I think the gist of this issue is https://webauthn-doc.spomky-labs.com/the-webauthn-server/the-easy-way/user-authentication

After the main authenticator authenticated the user, this bundle's authentication factor needs to do 3 things (mostly client side):

  1. Retrieve the required WebAuthn public key credentials from web-authn
  2. Use the JavaScript API to prompt the user (e.g. fingerprint)
  3. Send the signature received from JavaScript to web-authn to verify it
  4. If verified successfully, the auth factor is completed

From this description, it seems like it should be possible (but maybe my description is much to simplistic)


@Spomky if you have any questions regarding changes in the new security (or think things can be improved to better integrate web-authn), feel free to drop me a message on Slack. We want to have great support for modern security standards, and I strongly believe webauthn is one of those. I've also secretly been exploring if adding a Symfony UX component for web-authn makes sense (after seeing the talk you referenced on SymfonyWorld 2021), I can share more info (on Slack or an issue in your repository) if you want :)

Spomky commented 3 years ago

Hi,

I've just publish my preliminary work on supporting Webauthn. See PR #106. Please note that this PR is not mature at all and still misses almost everything.

  1. Retrieve the required WebAuthn public key credentials from web-authn
  2. Use the JavaScript API to prompt the user (e.g. fingerprint)
  3. Send the signature received from JavaScript to web-authn to verify it
  4. If verified successfully, the auth factor is completed

This is correct. From what I understand, the gathering of known public keys can be performed during the prepareAuthentication call. This corresponds to the step 1. Step 2 and 3 are on client side (documentation to be added).

Step 4 is handled by validateAuthenticationCode. Howver, I am not sure if the parameter $authenticationCode corresponds to the actual request body.

I propose you to continue the discussion on the PR thread. Let me know if you want access on the fork branch to directly propose modifications.

BR.

Spomky commented 3 years ago

@Spomky if you have any questions regarding changes in the new security (or think things can be improved to better integrate web-authn), feel free to drop me a message on Slack.

Many thanks. I have tons of questions! My main concerns are to maintain BC compatibility. I can see the 2FA bundle is acheiving that in a convenient way. I think I will start learning from it.

We want to have great support for modern security standards, and I strongly believe webauthn is one of those.

I am convinced of it too. For SF UX, you will find a working example I recently deployed on a project. webauthn_controller.zip It is quite easy to use:

<button
    {{ stimulus_controller('webauthn', {
        optionsUrl: '/login/options',
        actionUrl: '/login/check',
        successUrl: '/',
    }) }}
    data-action="webauthn#onLogin"
>
    Log me in!
</button>
tydoo commented 2 years ago

Hello,

Where is the project to implement webauthn as 2FA?

jbtronics commented 1 year ago

I have written a basic 2fa provider using Spomkys Web-Authn Framework: https://github.com/jbtronics/2fa-webauthn

It offers backwards compatibility with U2F keys registered via r/u2f-two-factor-bundle, so users can use their existing keys without re registering.