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

Webauthn authentication on Windows always prompts for windows security key #399

Open
j-boers-13 opened this issue Sep 7, 2023 · 4 comments

Comments

@j-boers-13
Copy link

Hi,

Let me start off by saying thank you for all the work on the ruby package and the wonderful examples you have provided.

I have been working on a Rails 7 app using webauthn-ruby gem for 2FA. In the frontend we use WebAuthnJSON. When logging in, first there is a step with email/password, after which we find the existing credentials and a user will need to authenticate with webauthn.

The problem I have been running into is, no matter what settings I use, in Windows (chrome), users always get prompted for a security key (usb) or with other settings they get prompted for windows hello sign in. After you cancel that step, you get to the normal chrome modal where you can select a a device to authenticate with. We want to skip the windows step, but can't figure out how to.

This issue is also present on https://webauthn.cedarcode.com/
However if you test on https://webauthn.io, this issue is not present.

Is this because of the gem or is it related to WebAuthnJSON?

This happens using the default settings and pretty much any other settings. We can get rid of the windows hello login by using:

create_options = WebAuthn::Credential.options_for_create(
  exclude:                 @authenticatable.webauthn_credentials.pluck(:external_id),
  user:                    {
    id:           @authenticatable.webauthn_id,
    display_name: @authenticatable.email,
    name:         @authenticatable.full_name
  },
  pub_key_cred_params: [
    {
      type: 'public-key',
      alg:  -7 # "ES256" as registered in the IANA COSE Algorithms registry
    },
    {
      type: 'public-key',
      alg:  -257 # Value registered by this specification for "RS256"
    }
  ],
  authenticator_selection: {
    resident_key:      'required', # We have tried every variation of this value as well
    user_verification: 'preferred' # We have tried every variation of this value as well
  }
)

Specifically setting the resident_key to required removes the step from the registering, but it doesn't remove the windows hello or security key step in authentication, so my problem persists. Could you point me into the right direction?

Thank you in advance!

@j-boers-13
Copy link
Author

I think I might have found the problem, webauthn-ruby by default doesnt do anything with transports, I would need to save those to my database and then add them to the allowed_credentials in order for it to properly prompt for the right credentials.

If I was expected to know this, feel free to close this issue.

@brauliomartinezlm
Copy link
Member

Hi @j-boers-13 ,

Thank you for the kind words and for brining up your problem here!

I started examining our gem's code on transports and you're right. We're not doing anything with it at the credential representation level. Closest hint to an answer in this topic can be found in our tests

I also did a bit of digging in the standard which states at 7.1 - step 23:

If the attestation statement attStmt verified successfully and is found to be trustworthy, then register the new credential with the account that was denoted in options.[user](https://www.w3.org/TR/webauthn-2/#dom-publickeycredentialcreationoptions-user):

Associate the user’s account with the [credentialId](https://www.w3.org/TR/webauthn-2/#credentialid) and [credentialPublicKey](https://www.w3.org/TR/webauthn-2/#credentialpublickey) in authData.[attestedCredentialData](https://www.w3.org/TR/webauthn-2/#attestedcredentialdata), as appropriate for the [Relying Party](https://www.w3.org/TR/webauthn-2/#relying-party)'s system.

Associate the [credentialId](https://www.w3.org/TR/webauthn-2/#credentialid) with a new stored [signature counter](https://www.w3.org/TR/webauthn-2/#signature-counter) value initialized to the value of authData.[signCount](https://www.w3.org/TR/webauthn-2/#signcount).

It is RECOMMENDED to also:

Associate the [credentialId](https://www.w3.org/TR/webauthn-2/#credentialid) with the transport hints returned by calling credential.[response](https://www.w3.org/TR/webauthn-2/#dom-publickeycredential-response).[getTransports()](https://www.w3.org/TR/webauthn-2/#dom-authenticatorattestationresponse-gettransports). This value SHOULD NOT be modified before or after storing it. It is RECOMMENDED to use this value to populate the [transports](https://www.w3.org/TR/webauthn-2/#dom-publickeycredentialdescriptor-transports) of the [allowCredentials](https://www.w3.org/TR/webauthn-2/#dom-publickeycredentialrequestoptions-allowcredentials) option in future [get()](https://w3c.github.io/webappsec-credential-management/#dom-credentialscontainer-get) calls to help the [client](https://www.w3.org/TR/webauthn-2/#client) know how to find a suitable [authenticator](https://www.w3.org/TR/webauthn-2/#authenticator).

Though it's not a validation or a mandatory step, I think we never paid much attention to the RECOMMENDED part of this step. I'd say that happened also due to browser implementation of the API was also reacting different on using the transports when sent on allow_credentials. I'm very open to:

  1. Document in the saving of the credential in the verification part of the Registration that transports should be saved.
  2. Add transports as another key passed in to PublicKeyCredential so it can be forwarded to the gem's user when storing credentials.

What do you think @santiagorodriguez96 @j-boers-13 ?

@santiagorodriguez96
Copy link
Contributor

I've opened a PR for adding an interface to access the transports: #421

@j-boers-13
Copy link
Author

Sounds good, that would potentially solve the issue. I also think it's an issue in windows specifically which they have changed recently. I tried it without changing anything in our code recently and i was able to use different authentication methods other than windows hello.

But adding the possibility for passing transports is definitely useful I think!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants